From 89a2ea17e21cd89715c0efc1e852dc404d643a4f Mon Sep 17 00:00:00 2001 From: veypi Date: Sun, 8 Feb 2026 22:24:24 +0800 Subject: [PATCH] fix upgrade bug --- cli/main.go | 14 +- ui/assets/vhtml.min.js | 2 +- ui/page/index.html | 2 +- ui/page/login.html | 45 +- ui/root.html | 3 +- ui/vhtml/axios.min.js | 3 + ui/vhtml/utils.js | 293 +++++++++++ ui/vhtml/v.js | 1128 ++++++++++++++++++++++++++++++++++++++++ ui/vhtml/vbus.js | 138 +++++ ui/vhtml/vcss.js | 566 ++++++++++++++++++++ ui/vhtml/vdev.js | 70 +++ ui/vhtml/vdevselect.js | 620 ++++++++++++++++++++++ ui/vhtml/verror.js | 89 ++++ ui/vhtml/vget.js | 322 ++++++++++++ ui/vhtml/vmessage.js | 531 +++++++++++++++++++ ui/vhtml/vproxy.js | 553 ++++++++++++++++++++ ui/vhtml/vrouter.js | 624 ++++++++++++++++++++++ 17 files changed, 4971 insertions(+), 32 deletions(-) create mode 100644 ui/vhtml/axios.min.js create mode 100644 ui/vhtml/utils.js create mode 100644 ui/vhtml/v.js create mode 100644 ui/vhtml/vbus.js create mode 100644 ui/vhtml/vcss.js create mode 100644 ui/vhtml/vdev.js create mode 100644 ui/vhtml/vdevselect.js create mode 100644 ui/vhtml/verror.js create mode 100644 ui/vhtml/vget.js create mode 100644 ui/vhtml/vmessage.js create mode 100644 ui/vhtml/vproxy.js create mode 100644 ui/vhtml/vrouter.js diff --git a/cli/main.go b/cli/main.go index 55826ba..9327288 100644 --- a/cli/main.go +++ b/cli/main.go @@ -17,16 +17,13 @@ import ( ) var cliOpts = &struct { - Host string `json:"host" short:"h` - Port int `json:"port" short:"p"` - LoggerPath string `json:"logger_path,omitempty"` - LoggerLevel string `json:"logger_level,omitempty"` + Host string `json:"host"` + Port int `json:"port" short:"p"` *cfg.Options }{ - Host: "0.0.0.0", - Port: 4000, - LoggerLevel: "debug", - Options: cfg.Config, + Host: "0.0.0.0", + Port: 4000, + Options: cfg.Config, } var ( @@ -50,7 +47,6 @@ func main() { } func runWeb() error { - logv.SetLevel(logv.AssertFuncErr(logv.ParseLevel(cliOpts.LoggerLevel))) server, err := vigo.New(vigo.WithHost(cliOpts.Host), vigo.WithPort(cliOpts.Port)) if err != nil { return err diff --git a/ui/assets/vhtml.min.js b/ui/assets/vhtml.min.js index dc8d416..84f7086 100644 --- a/ui/assets/vhtml.min.js +++ b/ui/assets/vhtml.min.js @@ -1 +1 @@ -var t;t=function(){const t=[],e=[];function n(){return`${performance.now().toString(36)}-${Math.random().toString(36).substring(2,5)}`}function o(t,e=new Set){if(t&&"object"==typeof t&&!e.has(t)){e.add(t);for(let n in t)o(t[n],e)}return t}setInterval((()=>{let n=new Set(e.splice(0)),o=0;for(let e of n)t[e]&&(t[e](),o++);return o}),25),window.$vupdate=e=>{t[e]()};var r=[];const i=Symbol("isProxy"),s=Symbol("DataID"),a=Symbol("bind"),c=Symbol("root"),l=Symbol("root arg");function u(t,e){t[c]=e,Object.keys(e).forEach((e=>{e in t||(t[e]=l)}))}function f(t){return!(!t||"object"!=typeof t||t instanceof Node||t instanceof Date||t instanceof RegExp||t instanceof Event||t.t||t.constructor!==Object&&t.constructor!==Array)}function h(t,e){if(!t||!t[i]||!f(e))return e;let n=t[a];if(!e[i]){if(Array.isArray(e)&&Array.isArray(t)){t.length=0;for(let n=0;n{e.hasOwnProperty(n)||delete t[n]})),Object.keys(e).forEach((n=>{t[n]?.[i]?t[n]=h(t[n],e[n]):t[n]=e[n]})),t}if(e[s]===t[s])return e;for(let o in n)if(e[a][o]?.indexOf){const t=e[a][o],r=new Set(t);for(let e of n[o])r.has(e)||(t.push(e),r.add(e))}else e[a][o]=n[o];for(let o in e)o in t&&t[o]?.[i]&&(e[o]=h(t[o],e[o]));return e}let d=!1;const p={console,window,prompt:prompt.bind(window),alert:alert.bind(window),confirm:confirm.bind(window),RegExp,document,Array,Object,Math,Date,JSON,Symbol,Number,eval,isNaN,parseInt,parseFloat,setTimeout:setTimeout.bind(window),setInterval:setInterval.bind(window),clearTimeout:clearTimeout.bind(window),clearInterval:clearInterval.bind(window),encodeURIComponent,btoa:btoa.bind(window),fetch:fetch.bind(window),TextDecoder,history,requestAnimationFrame:requestAnimationFrame.bind(window)};function m(t,e,n){const o=new Proxy(t,{has:(t,e)=>!0,get(o,r,i){let s;return"$data"===r?s=t:"$env"===r?s=e:r in o?s=Reflect.get(o,r,i):r in e?s=e[r]:n&&r in n?s=n[r]:r in p?s=p[r]:r in window&&(s=window[r]),s},set:(t,e,n,o)=>Reflect.set(t,e,n,o)});return o}const w=Object.getPrototypeOf((async function(){})).constructor;function b(t,e){if(t.startsWith("/"))return t;const n=e.substring(0,e.lastIndexOf("/")).split("/").filter((t=>""!==t)),o=t.split("/").filter((t=>""!==t));for(const r of o)if(".."===r)n.length>0&&n.pop();else{if("."===r)continue;n.push(r)}return"/"+n.join("/")}const y={Wrap:function o(p,m=void 0){const w=n();let b=!1;"[object Array]"==={}.toString.call(p)&&(b=!0),m&&u(p,m);const y={},v={get(t,e,n){if(e===s)return w;if(e===i)return!0;if(e===a)return y;const u=Reflect.get(t,e,n);if(u===l)return t[c][e];if("symbol"==typeof e&&d)return u;if("function"==typeof u)return u;let h=-1;if(r.length>0){let t=e;h=r[r.length-1],b&&(t=""),y.hasOwnProperty(t)?-1==y[t].indexOf(h)&&y[t].push(h):y[t]=[h]}if(window.vdev,f(u)&&!u[i]){let r=o(u,void 0);return Reflect.set(t,e,r,n),r}return u},set(n,o,s,a){const u=Reflect.get(n,o,a);if(u===l)return n[c][o]=s,!0;if(u===s)return!0;if(d)return Reflect.set(n,o,s,a);let p=!0;if(Array.isArray(s)&&Array.isArray(u)){d=!0,u.length=0;for(let t=0;t{n(e())})):t.push(e);try{s=e(),i&&i.deep&&o(s)}catch(g){}finally{r.pop()}return"function"==typeof n&&n(s),a},Cancel:function(e){e>=0&&et.trim()))}const i=await import(t);"string"==typeof o?i.default?e[o]=i.default:e[o]=i:o.forEach((t=>{t in i?e[t]=i[t]:t in i.default&&(e[t]=i.default[t])}))}catch(l){}}return s.trim()}};class v{constructor(){this.events={}}on(t,e,n=null){if("function"!=typeof e)throw Error("\u56de\u8c03\u51fd\u6570\u5fc5\u987b\u662f\u4e00\u4e2a\u51fd\u6570");this.events[t]||(this.events[t]=[]);const o={callback:e,context:n};return this.events[t].push(o),()=>this.off(t,e,n)}once(t,e,n=null){const o=(...r)=>{this.off(t,o,n),e.apply(n,r)};return this.on(t,o,n)}off(t,e=null,n=null){this.events[t]&&(e?(this.events[t]=this.events[t].filter((t=>!(t.callback===e&&t.context===n))),0===this.events[t].length&&delete this.events[t]):delete this.events[t])}emit(t,...e){this.events[t]&&[...this.events[t]].forEach((t=>{try{t.callback.apply(t.context,e)}catch(n){}}))}listenerCount(t){return this.events[t]?this.events[t].length:0}eventNames(){return Object.keys(this.events)}removeAllListeners(){this.events={}}hasListeners(t){return this.listenerCount(t)>0}}function g(t,e){return function(){return t.apply(e,arguments)}}const{toString:x}=Object.prototype,{getPrototypeOf:R}=Object,{iterator:k,toStringTag:O}=Symbol,T=(E=Object.create(null),t=>{const e=x.call(t);return E[e]||(E[e]=e.slice(8,-1).toLowerCase())});var E;const S=t=>(t=t.toLowerCase(),e=>T(e)===t),A=t=>e=>typeof e===t,{isArray:j}=Array,$=A("undefined"),N=S("ArrayBuffer"),P=A("string"),C=A("function"),U=A("number"),F=t=>null!==t&&"object"==typeof t,D=t=>{if("object"!==T(t))return!1;const e=R(t);return!(null!==e&&e!==Object.prototype&&null!==Object.getPrototypeOf(e)||O in t||k in t)},L=S("Date"),I=S("File"),z=S("Blob"),M=S("FileList"),q=S("URLSearchParams"),[B,_,H,V]=["ReadableStream","Request","Response","Headers"].map(S);function X(t,e,{allOwnKeys:n=!1}={}){if(null==t)return;let o,r;if("object"!=typeof t&&(t=[t]),j(t))for(o=0,r=t.length;r>o;o++)e.call(null,t[o],o,t);else{const r=n?Object.getOwnPropertyNames(t):Object.keys(t),i=r.length;let s;for(o=0;i>o;o++)s=r[o],e.call(null,t[s],s,t)}}function J(t,e){e=e.toLowerCase();const n=Object.keys(t);let o,r=n.length;for(;r-- >0;)if(o=n[r],e===o.toLowerCase())return o;return null}const W="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:global,K=t=>!$(t)&&t!==W,G=(Z="undefined"!=typeof Uint8Array&&R(Uint8Array),t=>Z&&t instanceof Z);var Z;const Y=S("HTMLFormElement"),Q=(({hasOwnProperty:t})=>(e,n)=>t.call(e,n))(Object.prototype),tt=S("RegExp"),et=(t,e)=>{const n=Object.getOwnPropertyDescriptors(t),o={};X(n,((n,r)=>{let i;!1!==(i=e(n,r,t))&&(o[r]=i||n)})),Object.defineProperties(t,o)},nt=S("AsyncFunction"),ot=(rt="function"==typeof setImmediate,it=C(W.postMessage),rt?setImmediate:it?(st="axios@"+Math.random(),at=[],W.addEventListener("message",(({source:t,data:e})=>{t===W&&e===st&&at.length&&at.shift()()}),!1),t=>{at.push(t),W.postMessage(st,"*")}):t=>setTimeout(t));var rt,it,st,at;const ct="undefined"!=typeof queueMicrotask?queueMicrotask.bind(W):"undefined"!=typeof process&&process.nextTick||ot,lt={isArray:j,isArrayBuffer:N,isBuffer:function(t){return null!==t&&!$(t)&&null!==t.constructor&&!$(t.constructor)&&C(t.constructor.isBuffer)&&t.constructor.isBuffer(t)},isFormData:t=>{let e;return t&&("function"==typeof FormData&&t instanceof FormData||C(t.append)&&("formdata"===(e=T(t))||"object"===e&&C(t.toString)&&"[object FormData]"===t.toString()))},isArrayBufferView:function(t){let e;return e="undefined"!=typeof ArrayBuffer&&ArrayBuffer.isView?ArrayBuffer.isView(t):t&&t.buffer&&N(t.buffer),e},isString:P,isNumber:U,isBoolean:t=>!0===t||!1===t,isObject:F,isPlainObject:D,isReadableStream:B,isRequest:_,isResponse:H,isHeaders:V,isUndefined:$,isDate:L,isFile:I,isBlob:z,isRegExp:tt,isFunction:C,isStream:t=>F(t)&&C(t.pipe),isURLSearchParams:q,isTypedArray:G,isFileList:M,forEach:X,merge:function t(){const{caseless:e}=K(this)&&this||{},n={},o=(o,r)=>{const i=e&&J(n,r)||r;D(n[i])&&D(o)?n[i]=t(n[i],o):D(o)?n[i]=t({},o):j(o)?n[i]=o.slice():n[i]=o};for(let r=0,i=arguments.length;i>r;r++)arguments[r]&&X(arguments[r],o);return n},extend:(t,e,n,{allOwnKeys:o}={})=>(X(e,((e,o)=>{n&&C(e)?t[o]=g(e,n):t[o]=e}),{allOwnKeys:o}),t),trim:t=>t.trim?t.trim():t.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,""),stripBOM:t=>(65279===t.charCodeAt(0)&&(t=t.slice(1)),t),inherits:(t,e,n,o)=>{t.prototype=Object.create(e.prototype,o),t.prototype.constructor=t,Object.defineProperty(t,"super",{value:e.prototype}),n&&Object.assign(t.prototype,n)},toFlatObject:(t,e,n,o)=>{let r,i,s;const a={};if(e=e||{},null==t)return e;do{for(r=Object.getOwnPropertyNames(t),i=r.length;i-- >0;)s=r[i],o&&!o(s,t,e)||a[s]||(e[s]=t[s],a[s]=!0);t=!1!==n&&R(t)}while(t&&(!n||n(t,e))&&t!==Object.prototype);return e},kindOf:T,kindOfTest:S,endsWith:(t,e,n)=>{t+="",(void 0===n||n>t.length)&&(n=t.length),n-=e.length;const o=t.indexOf(e,n);return-1!==o&&o===n},toArray:t=>{if(!t)return null;if(j(t))return t;let e=t.length;if(!U(e))return null;const n=Array(e);for(;e-- >0;)n[e]=t[e];return n},forEachEntry:(t,e)=>{const n=(t&&t[k]).call(t);let o;for(;(o=n.next())&&!o.done;){const n=o.value;e.call(t,n[0],n[1])}},matchAll:(t,e)=>{let n;const o=[];for(;null!==(n=t.exec(e));)o.push(n);return o},isHTMLForm:Y,hasOwnProperty:Q,hasOwnProp:Q,reduceDescriptors:et,freezeMethods:t=>{et(t,((e,n)=>{if(C(t)&&-1!==["arguments","caller","callee"].indexOf(n))return!1;const o=t[n];C(o)&&(e.enumerable=!1,"writable"in e?e.writable=!1:e.set||(e.set=()=>{throw Error("Can not rewrite read-only method '"+n+"'")}))}))},toObjectSet:(t,e)=>{const n={},o=t=>{t.forEach((t=>{n[t]=!0}))};return j(t)?o(t):o((t+"").split(e)),n},toCamelCase:t=>t.toLowerCase().replace(/[-_\s]([a-z\d])(\w*)/g,(function(t,e,n){return e.toUpperCase()+n})),noop:()=>{},toFiniteNumber:(t,e)=>null!=t&&Number.isFinite(t=+t)?t:e,findKey:J,global:W,isContextDefined:K,isSpecCompliantForm:function(t){return!!(t&&C(t.append)&&"FormData"===t[O]&&t[k])},toJSONObject:t=>{const e=[,,,,,,,,,,],n=(t,o)=>{if(F(t)){if(e.indexOf(t)>=0)return;if(!("toJSON"in t)){e[o]=t;const r=j(t)?[]:{};return X(t,((t,e)=>{const i=n(t,o+1);!$(i)&&(r[e]=i)})),e[o]=void 0,r}}return t};return n(t,0)},isAsyncFn:nt,isThenable:t=>t&&(F(t)||C(t))&&C(t.then)&&C(t.catch),setImmediate:ot,asap:ct,isIterable:t=>null!=t&&C(t[k])};function ut(t,e,n,o,r){Error.call(this),Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):this.stack=Error().stack,this.message=t,this.name="AxiosError",e&&(this.code=e),n&&(this.config=n),o&&(this.request=o),r&&(this.response=r,this.status=r.status?r.status:null)}lt.inherits(ut,Error,{toJSON:function(){return{message:this.message,name:this.name,description:this.description,number:this.number,fileName:this.fileName,lineNumber:this.lineNumber,columnNumber:this.columnNumber,stack:this.stack,config:lt.toJSONObject(this.config),code:this.code,status:this.status}}});const ft=ut.prototype,ht={};function dt(t){return lt.isPlainObject(t)||lt.isArray(t)}function pt(t){return lt.endsWith(t,"[]")?t.slice(0,-2):t}function mt(t,e,n){return t?t.concat(e).map((function(t,e){return t=pt(t),!n&&e?"["+t+"]":t})).join(n?".":""):e}["ERR_BAD_OPTION_VALUE","ERR_BAD_OPTION","ECONNABORTED","ETIMEDOUT","ERR_NETWORK","ERR_FR_TOO_MANY_REDIRECTS","ERR_DEPRECATED","ERR_BAD_RESPONSE","ERR_BAD_REQUEST","ERR_CANCELED","ERR_NOT_SUPPORT","ERR_INVALID_URL"].forEach((t=>{ht[t]={value:t}})),Object.defineProperties(ut,ht),Object.defineProperty(ft,"isAxiosError",{value:!0}),ut.from=(t,e,n,o,r,i)=>{const s=Object.create(ft);return lt.toFlatObject(t,s,(function(t){return t!==Error.prototype}),(t=>"isAxiosError"!==t)),ut.call(s,t.message,e,n,o,r),s.cause=t,s.name=t.name,i&&Object.assign(s,i),s};const wt=lt.toFlatObject(lt,{},null,(function(t){return/^is[A-Z]/.test(t)}));function bt(t,e,n){if(!lt.isObject(t))throw new TypeError("target must be an object");e=e||new FormData;const o=(n=lt.toFlatObject(n,{metaTokens:!0,dots:!1,indexes:!1},!1,(function(t,e){return!lt.isUndefined(e[t])}))).metaTokens,r=n.visitor||l,i=n.dots,s=n.indexes,a=(n.Blob||"undefined"!=typeof Blob&&Blob)&<.isSpecCompliantForm(e);if(!lt.isFunction(r))throw new TypeError("visitor must be a function");function c(t){if(null===t)return"";if(lt.isDate(t))return t.toISOString();if(lt.isBoolean(t))return t.toString();if(!a&<.isBlob(t))throw new ut("Blob is not supported. Use a Buffer instead.");return lt.isArrayBuffer(t)||lt.isTypedArray(t)?a&&"function"==typeof Blob?new Blob([t]):Buffer.from(t):t}function l(t,n,r){let a=t;if(t&&!r&&"object"==typeof t)if(lt.endsWith(n,"{}"))n=o?n:n.slice(0,-2),t=JSON.stringify(t);else if(lt.isArray(t)&&function(t){return lt.isArray(t)&&!t.some(dt)}(t)||(lt.isFileList(t)||lt.endsWith(n,"[]"))&&(a=lt.toArray(t)))return n=pt(n),a.forEach((function(t,o){!lt.isUndefined(t)&&null!==t&&e.append(!0===s?mt([n],o,i):null===s?n:n+"[]",c(t))})),!1;return!!dt(t)||(e.append(mt(r,n,i),c(t)),!1)}const u=[],f=Object.assign(wt,{defaultVisitor:l,convertValue:c,isVisitable:dt});if(!lt.isObject(t))throw new TypeError("data must be an object");return function t(n,o){if(!lt.isUndefined(n)){if(-1!==u.indexOf(n))throw Error("Circular reference detected in "+o.join("."));u.push(n),lt.forEach(n,(function(n,i){!0===(!(lt.isUndefined(n)||null===n)&&r.call(e,n,lt.isString(i)?i.trim():i,o,f))&&t(n,o?o.concat(i):[i])})),u.pop()}}(t),e}function yt(t){const e={"!":"%21","'":"%27","(":"%28",")":"%29","~":"%7E","%20":"+","%00":"\0"};return encodeURIComponent(t).replace(/[!'()~]|%20|%00/g,(function(t){return e[t]}))}function vt(t,e){this.o=[],t&&bt(t,this,e)}const gt=vt.prototype;function xt(t){return encodeURIComponent(t).replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+").replace(/%5B/gi,"[").replace(/%5D/gi,"]")}function Rt(t,e,n){if(!e)return t;const o=n&&n.encode||xt;lt.isFunction(n)&&(n={serialize:n});const r=n&&n.serialize;let i;if(i=r?r(e,n):lt.isURLSearchParams(e)?e.toString():new vt(e,n).toString(o),i){const e=t.indexOf("#");-1!==e&&(t=t.slice(0,e)),t+=(-1===t.indexOf("?")?"?":"&")+i}return t}gt.append=function(t,e){this.o.push([t,e])},gt.toString=function(t){const e=t?function(e){return t.call(this,e,yt)}:yt;return this.o.map((function(t){return e(t[0])+"="+e(t[1])}),"").join("&")};const kt=class{constructor(){this.handlers=[]}use(t,e,n){return this.handlers.push({fulfilled:t,rejected:e,synchronous:!!n&&n.synchronous,runWhen:n?n.runWhen:null}),this.handlers.length-1}eject(t){this.handlers[t]&&(this.handlers[t]=null)}clear(){this.handlers&&(this.handlers=[])}forEach(t){lt.forEach(this.handlers,(function(e){null!==e&&t(e)}))}},Ot={silentJSONParsing:!0,forcedJSONParsing:!0,clarifyTimeoutError:!1},Tt={isBrowser:!0,classes:{URLSearchParams:"undefined"!=typeof URLSearchParams?URLSearchParams:vt,FormData:"undefined"!=typeof FormData?FormData:null,Blob:"undefined"!=typeof Blob?Blob:null},protocols:["http","https","file","blob","url","data"]},Et="undefined"!=typeof window&&"undefined"!=typeof document,St="object"==typeof navigator&&navigator||void 0,At=Et&&(!St||0>["ReactNative","NativeScript","NS"].indexOf(St.product)),jt="undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope&&"function"==typeof self.importScripts,$t=Et&&window.location.href||"http://localhost",Nt={...Object.freeze({__proto__:null,hasBrowserEnv:Et,hasStandardBrowserWebWorkerEnv:jt,hasStandardBrowserEnv:At,navigator:St,origin:$t}),...Tt};function Pt(t){function e(t,n,o,r){let i=t[r++];if("__proto__"===i)return!0;const s=Number.isFinite(+i),a=r>=t.length;return i=!i&<.isArray(o)?o.length:i,a?(lt.hasOwnProp(o,i)?o[i]=[o[i],n]:o[i]=n,!s):(o[i]&<.isObject(o[i])||(o[i]=[]),e(t,n,o[i],r)&<.isArray(o[i])&&(o[i]=function(t){const e={},n=Object.keys(t);let o;const r=n.length;let i;for(o=0;r>o;o++)i=n[o],e[i]=t[i];return e}(o[i])),!s)}if(lt.isFormData(t)&<.isFunction(t.entries)){const n={};return lt.forEachEntry(t,((t,o)=>{e(function(t){return lt.matchAll(/\w+|\[(\w*)]/g,t).map((t=>"[]"===t[0]?"":t[1]||t[0]))}(t),o,n,0)})),n}return null}const Ct={transitional:Ot,adapter:["xhr","http","fetch"],transformRequest:[function(t,e){const n=e.getContentType()||"",o=n.indexOf("application/json")>-1,r=lt.isObject(t);if(r&<.isHTMLForm(t)&&(t=new FormData(t)),lt.isFormData(t))return o?JSON.stringify(Pt(t)):t;if(lt.isArrayBuffer(t)||lt.isBuffer(t)||lt.isStream(t)||lt.isFile(t)||lt.isBlob(t)||lt.isReadableStream(t))return t;if(lt.isArrayBufferView(t))return t.buffer;if(lt.isURLSearchParams(t))return e.setContentType("application/x-www-form-urlencoded;charset=utf-8",!1),t.toString();let i;if(r){if(n.indexOf("application/x-www-form-urlencoded")>-1)return function(t,e){return bt(t,new Nt.classes.URLSearchParams,Object.assign({visitor:function(t,e,n,o){return Nt.isNode&<.isBuffer(t)?(this.append(e,t.toString("base64")),!1):o.defaultVisitor.apply(this,arguments)}},e))}(t,this.formSerializer).toString();if((i=lt.isFileList(t))||n.indexOf("multipart/form-data")>-1){const e=this.env&&this.env.FormData;return bt(i?{"files[]":t}:t,e&&new e,this.formSerializer)}}return r||o?(e.setContentType("application/json",!1),function(t){if(lt.isString(t))try{return(0,JSON.parse)(t),lt.trim(t)}catch(t){if("SyntaxError"!==t.name)throw t}return(0,JSON.stringify)(t)}(t)):t}],transformResponse:[function(t){const e=this.transitional||Ct.transitional,n=e&&e.forcedJSONParsing,o="json"===this.responseType;if(lt.isResponse(t)||lt.isReadableStream(t))return t;if(t&<.isString(t)&&(n&&!this.responseType||o)){const n=!(e&&e.silentJSONParsing)&&o;try{return JSON.parse(t)}catch(t){if(n){if("SyntaxError"===t.name)throw ut.from(t,ut.ERR_BAD_RESPONSE,this,null,this.response);throw t}}}return t}],timeout:0,xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",maxContentLength:-1,maxBodyLength:-1,env:{FormData:Nt.classes.FormData,Blob:Nt.classes.Blob},validateStatus:function(t){return t>=200&&300>t},headers:{common:{Accept:"application/json, text/plain, */*","Content-Type":void 0}}};lt.forEach(["delete","get","head","post","put","patch"],(t=>{Ct.headers[t]={}}));const Ut=Ct,Ft=lt.toObjectSet(["age","authorization","content-length","content-type","etag","expires","from","host","if-modified-since","if-unmodified-since","last-modified","location","max-forwards","proxy-authorization","referer","retry-after","user-agent"]),Dt=Symbol("internals");function Lt(t){return t&&(t+"").trim().toLowerCase()}function It(t){return!1===t||null==t?t:lt.isArray(t)?t.map(It):t+""}function zt(t,e,n,o,r){return lt.isFunction(o)?o.call(this,e,n):(r&&(e=n),lt.isString(e)?lt.isString(o)?-1!==e.indexOf(o):lt.isRegExp(o)?o.test(e):void 0:void 0)}class Mt{constructor(t){t&&this.set(t)}set(t,e,n){const o=this;function r(t,e,n){const r=Lt(e);if(!r)throw Error("header name must be a non-empty string");const i=lt.findKey(o,r);(!i||void 0===o[i]||!0===n||void 0===n&&!1!==o[i])&&(o[i||e]=It(t))}const i=(t,e)=>lt.forEach(t,((t,n)=>r(t,n,e)));if(lt.isPlainObject(t)||t instanceof this.constructor)i(t,e);else if(lt.isString(t)&&(t=t.trim())&&!/^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(t.trim()))i((t=>{const e={};let n,o,r;return t&&t.split("\n").forEach((function(t){r=t.indexOf(":"),n=t.substring(0,r).trim().toLowerCase(),o=t.substring(r+1).trim(),!n||e[n]&&Ft[n]||("set-cookie"===n?e[n]?e[n].push(o):e[n]=[o]:e[n]=e[n]?e[n]+", "+o:o)})),e})(t),e);else if(lt.isObject(t)&<.isIterable(t)){let n,o,r={};for(const e of t){if(!lt.isArray(e))throw TypeError("Object iterator must return a key-value pair");r[o=e[0]]=(n=r[o])?lt.isArray(n)?[...n,e[1]]:[n,e[1]]:e[1]}i(r,e)}else null!=t&&r(e,t,n);return this}get(t,e){if(t=Lt(t)){const n=lt.findKey(this,t);if(n){const t=this[n];if(!e)return t;if(!0===e)return function(t){const e=Object.create(null),n=/([^\s,;=]+)\s*(?:=\s*([^,;]+))?/g;let o;for(;o=n.exec(t);)e[o[1]]=o[2];return e}(t);if(lt.isFunction(e))return e.call(this,t,n);if(lt.isRegExp(e))return e.exec(t);throw new TypeError("parser must be boolean|regexp|function")}}}has(t,e){if(t=Lt(t)){const n=lt.findKey(this,t);return!(!n||void 0===this[n]||e&&!zt(0,this[n],n,e))}return!1}delete(t,e){const n=this;let o=!1;function r(t){if(t=Lt(t)){const r=lt.findKey(n,t);!r||e&&!zt(0,n[r],r,e)||(delete n[r],o=!0)}}return lt.isArray(t)?t.forEach(r):r(t),o}clear(t){const e=Object.keys(this);let n=e.length,o=!1;for(;n--;){const r=e[n];t&&!zt(0,this[r],r,t,!0)||(delete this[r],o=!0)}return o}normalize(t){const e=this,n={};return lt.forEach(this,((o,r)=>{const i=lt.findKey(n,r);if(i)return e[i]=It(o),void delete e[r];const s=t?function(t){return t.trim().toLowerCase().replace(/([a-z\d])(\w*)/g,((t,e,n)=>e.toUpperCase()+n))}(r):(r+"").trim();s!==r&&delete e[r],e[s]=It(o),n[s]=!0})),this}concat(...t){return this.constructor.concat(this,...t)}toJSON(t){const e=Object.create(null);return lt.forEach(this,((n,o)=>{null!=n&&!1!==n&&(e[o]=t&<.isArray(n)?n.join(", "):n)})),e}[Symbol.iterator](){return Object.entries(this.toJSON())[Symbol.iterator]()}toString(){return Object.entries(this.toJSON()).map((([t,e])=>t+": "+e)).join("\n")}getSetCookie(){return this.get("set-cookie")||[]}get[Symbol.toStringTag](){return"AxiosHeaders"}static from(t){return t instanceof this?t:new this(t)}static concat(t,...e){const n=new this(t);return e.forEach((t=>n.set(t))),n}static accessor(t){const e=(this[Dt]=this[Dt]={accessors:{}}).accessors,n=this.prototype;function o(t){const o=Lt(t);e[o]||(function(t,e){const n=lt.toCamelCase(" "+e);["get","set","has"].forEach((o=>{Object.defineProperty(t,o+n,{value:function(t,n,r){return this[o].call(this,e,t,n,r)},configurable:!0})}))}(n,t),e[o]=!0)}return lt.isArray(t)?t.forEach(o):o(t),this}}Mt.accessor(["Content-Type","Content-Length","Accept","Accept-Encoding","User-Agent","Authorization"]),lt.reduceDescriptors(Mt.prototype,(({value:t},e)=>{let n=e[0].toUpperCase()+e.slice(1);return{get:()=>t,set(t){this[n]=t}}})),lt.freezeMethods(Mt);const qt=Mt;function Bt(t,e){const n=this||Ut,o=e||n,r=qt.from(o.headers);let i=o.data;return lt.forEach(t,(function(t){i=t.call(n,i,r.normalize(),e?e.status:void 0)})),r.normalize(),i}function _t(t){return!(!t||!t.i)}function Ht(t,e,n){ut.call(this,t??"canceled",ut.ERR_CANCELED,e,n),this.name="CanceledError"}function Vt(t,e,n){const o=n.config.validateStatus;n.status&&o&&!o(n.status)?e(new ut("Request failed with status code "+n.status,[ut.ERR_BAD_REQUEST,ut.ERR_BAD_RESPONSE][Math.floor(n.status/100)-4],n.config,n.request,n)):t(n)}lt.inherits(Ht,ut,{i:!0});const Xt=(t,e,n=3)=>{let o=0;const r=function(t,e){const n=Array(t=t||10),o=Array(t);let r,i=0,s=0;return e=void 0!==e?e:1e3,function(a){const c=Date.now(),l=o[s];r||(r=c),n[i]=a,o[i]=c;let u=s,f=0;for(;u!==i;)f+=n[u++],u%=t;if(i=(i+1)%t,i===s&&(s=(s+1)%t),e>c-r)return;const h=l&&c-l;return h?Math.round(1e3*f/h):void 0}}(50,250);return function(t,e){let n,o,r=0,i=1e3/e;const s=(e,i=Date.now())=>{r=i,n=null,o&&(clearTimeout(o),o=null),t.apply(null,e)};return[(...t)=>{const e=Date.now(),a=e-r;i>a?(n=t,o||(o=setTimeout((()=>{o=null,s(n)}),i-a))):s(t,e)},()=>n&&s(n)]}((n=>{const i=n.loaded,s=n.lengthComputable?n.total:void 0,a=i-o,c=r(a);o=i,t({loaded:i,total:s,progress:s?i/s:void 0,bytes:a,rate:c||void 0,estimated:c&&s&&s>=i?(s-i)/c:void 0,event:n,lengthComputable:null!=s,[e?"download":"upload"]:!0})}),n)},Jt=(t,e)=>{const n=null!=t;return[o=>e[0]({lengthComputable:n,total:t,loaded:o}),e[1]]},Wt=t=>(...e)=>lt.asap((()=>t(...e))),Kt=Nt.hasStandardBrowserEnv?((t,e)=>n=>(n=new URL(n,Nt.origin),t.protocol===n.protocol&&t.host===n.host&&(e||t.port===n.port)))(new URL(Nt.origin),Nt.navigator&&/(msie|trident)/i.test(Nt.navigator.userAgent)):()=>!0,Gt=Nt.hasStandardBrowserEnv?{write(t,e,n,o,r,i){const s=[t+"="+encodeURIComponent(e)];lt.isNumber(n)&&s.push("expires="+new Date(n).toGMTString()),lt.isString(o)&&s.push("path="+o),lt.isString(r)&&s.push("domain="+r),!0===i&&s.push("secure"),document.cookie=s.join("; ")},read(t){const e=document.cookie.match(RegExp("(^|;\\s*)("+t+")=([^;]*)"));return e?decodeURIComponent(e[3]):null},remove(t){this.write(t,"",Date.now()-864e5)}}:{write(){},read:()=>null,remove(){}};function Zt(t,e,n){return!t||/^([a-z][a-z\d+\-.]*:)?\/\//i.test(e)&&0!=n?e:function(t,e){return e?t.replace(/\/?\/$/,"")+"/"+e.replace(/^\/+/,""):t}(t,e)}const Yt=t=>t instanceof qt?{...t}:t;function Qt(t,e){e=e||{};const n={};function o(t,e,n,o){return lt.isPlainObject(t)&<.isPlainObject(e)?lt.merge.call({caseless:o},t,e):lt.isPlainObject(e)?lt.merge({},e):lt.isArray(e)?e.slice():e}function r(t,e,n,r){return lt.isUndefined(e)?lt.isUndefined(t)?void 0:o(void 0,t,0,r):o(t,e,0,r)}function i(t,e){if(!lt.isUndefined(e))return o(void 0,e)}function s(t,e){return lt.isUndefined(e)?lt.isUndefined(t)?void 0:o(void 0,t):o(void 0,e)}function a(n,r,i){return i in e?o(n,r):i in t?o(void 0,n):void 0}const c={url:i,method:i,data:i,baseURL:s,transformRequest:s,transformResponse:s,paramsSerializer:s,timeout:s,timeoutMessage:s,withCredentials:s,withXSRFToken:s,adapter:s,responseType:s,xsrfCookieName:s,xsrfHeaderName:s,onUploadProgress:s,onDownloadProgress:s,decompress:s,maxContentLength:s,maxBodyLength:s,beforeRedirect:s,transport:s,httpAgent:s,httpsAgent:s,cancelToken:s,socketPath:s,responseEncoding:s,validateStatus:a,headers:(t,e,n)=>r(Yt(t),Yt(e),0,!0)};return lt.forEach(Object.keys(Object.assign({},t,e)),(function(o){const i=c[o]||r,s=i(t[o],e[o],o);lt.isUndefined(s)&&i!==a||(n[o]=s)})),n}const te=t=>{const e=Qt({},t);let n,{data:o,withXSRFToken:r,xsrfHeaderName:i,xsrfCookieName:s,headers:a,auth:c}=e;if(e.headers=a=qt.from(a),e.url=Rt(Zt(e.baseURL,e.url,e.allowAbsoluteUrls),t.params,t.paramsSerializer),c&&a.set("Authorization","Basic "+btoa((c.username||"")+":"+(c.password?unescape(encodeURIComponent(c.password)):""))),lt.isFormData(o))if(Nt.hasStandardBrowserEnv||Nt.hasStandardBrowserWebWorkerEnv)a.setContentType(void 0);else if(!1!==(n=a.getContentType())){const[t,...e]=n?n.split(";").map((t=>t.trim())).filter(Boolean):[];a.setContentType([t||"multipart/form-data",...e].join("; "))}if(Nt.hasStandardBrowserEnv&&(r&<.isFunction(r)&&(r=r(e)),r||!1!==r&&Kt(e.url))){const t=i&&s&&Gt.read(s);t&&a.set(i,t)}return e},ee="undefined"!=typeof XMLHttpRequest&&function(t){return new Promise((function(e,n){const o=te(t);let r=o.data;const i=qt.from(o.headers).normalize();let s,a,c,l,u,{responseType:f,onUploadProgress:h,onDownloadProgress:d}=o;function p(){l&&l(),u&&u(),o.cancelToken&&o.cancelToken.unsubscribe(s),o.signal&&o.signal.removeEventListener("abort",s)}let m=new XMLHttpRequest;function w(){if(!m)return;const o=qt.from("getAllResponseHeaders"in m&&m.getAllResponseHeaders());Vt((function(t){e(t),p()}),(function(t){n(t),p()}),{data:f&&"text"!==f&&"json"!==f?m.response:m.responseText,status:m.status,statusText:m.statusText,headers:o,config:t,request:m}),m=null}m.open(o.method.toUpperCase(),o.url,!0),m.timeout=o.timeout,"onloadend"in m?m.onloadend=w:m.onreadystatechange=function(){m&&4===m.readyState&&(0!==m.status||m.responseURL&&0===m.responseURL.indexOf("file:"))&&setTimeout(w)},m.onabort=function(){m&&(n(new ut("Request aborted",ut.ECONNABORTED,t,m)),m=null)},m.onerror=function(){n(new ut("Network Error",ut.ERR_NETWORK,t,m)),m=null},m.ontimeout=function(){let e=o.timeout?"timeout of "+o.timeout+"ms exceeded":"timeout exceeded";const r=o.transitional||Ot;o.timeoutErrorMessage&&(e=o.timeoutErrorMessage),n(new ut(e,r.clarifyTimeoutError?ut.ETIMEDOUT:ut.ECONNABORTED,t,m)),m=null},void 0===r&&i.setContentType(null),"setRequestHeader"in m&<.forEach(i.toJSON(),(function(t,e){m.setRequestHeader(e,t)})),lt.isUndefined(o.withCredentials)||(m.withCredentials=!!o.withCredentials),f&&"json"!==f&&(m.responseType=o.responseType),d&&([c,u]=Xt(d,!0),m.addEventListener("progress",c)),h&&m.upload&&([a,l]=Xt(h),m.upload.addEventListener("progress",a),m.upload.addEventListener("loadend",l)),(o.cancelToken||o.signal)&&(s=e=>{m&&(n(!e||e.type?new Ht(null,t,m):e),m.abort(),m=null)},o.cancelToken&&o.cancelToken.subscribe(s),o.signal&&(o.signal.aborted?s():o.signal.addEventListener("abort",s)));const b=function(t){const e=/^([-+\w]{1,25})(:?\/\/|:)/.exec(t);return e&&e[1]||""}(o.url);b&&-1===Nt.protocols.indexOf(b)?n(new ut("Unsupported protocol "+b+":",ut.ERR_BAD_REQUEST,t)):m.send(r||null)}))},ne=(t,e)=>{const{length:n}=t=t?t.filter(Boolean):[];if(e||n){let n,o=new AbortController;const r=function(t){if(!n){n=!0,s();const e=t instanceof Error?t:this.reason;o.abort(e instanceof ut?e:new Ht(e instanceof Error?e.message:e))}};let i=e&&setTimeout((()=>{i=null,r(new ut(`timeout ${e} of ms exceeded`,ut.ETIMEDOUT))}),e);const s=()=>{t&&(i&&clearTimeout(i),i=null,t.forEach((t=>{t.unsubscribe?t.unsubscribe(r):t.removeEventListener("abort",r)})),t=null)};t.forEach((t=>t.addEventListener("abort",r)));const{signal:a}=o;return a.unsubscribe=()=>lt.asap(s),a}},oe=function*(t,e){let n=t.byteLength;if(e>n)return void(yield t);let o,r=0;for(;n>r;)o=r+e,yield t.slice(r,o),r=o},re=(t,e,n,o)=>{const r=async function*(t,e){for await(const n of async function*(t){if(t[Symbol.asyncIterator])return void(yield*t);const e=t.getReader();try{for(;;){const{done:t,value:n}=await e.read();if(t)break;yield n}}finally{await e.cancel()}}(t))yield*oe(n,e)}(t,e);let i,s=0,a=t=>{i||(i=!0,o&&o(t))};return new ReadableStream({async pull(t){try{const{done:e,value:o}=await r.next();if(e)return a(),void t.close();let i=o.byteLength;if(n){let t=s+=i;n(t)}t.enqueue(new Uint8Array(o))}catch(t){throw a(t),t}},cancel:t=>(a(t),r.return())},{highWaterMark:2})},ie="function"==typeof fetch&&"function"==typeof Request&&"function"==typeof Response,se=ie&&"function"==typeof ReadableStream,ae=ie&&("function"==typeof TextEncoder?(ce=new TextEncoder,t=>ce.encode(t)):async t=>new Uint8Array(await new Response(t).arrayBuffer()));var ce;const le=(t,...e)=>{try{return!!t(...e)}catch(t){return!1}},ue=se&&le((()=>{let t=!1;const e=new Request(Nt.origin,{body:new ReadableStream,method:"POST",get duplex(){return t=!0,"half"}}).headers.has("Content-Type");return t&&!e})),fe=se&&le((()=>lt.isReadableStream(new Response("").body))),he={stream:fe&&(t=>t.body)};var de;ie&&(de=new Response,["text","arrayBuffer","blob","formData","stream"].forEach((t=>{!he[t]&&(he[t]=lt.isFunction(de[t])?e=>e[t]():(e,n)=>{throw new ut(`Response type '${t}' is not supported`,ut.ERR_NOT_SUPPORT,n)})})));const pe={http:null,xhr:ee,fetch:ie&&(async t=>{let{url:e,method:n,data:o,signal:r,cancelToken:i,timeout:s,onDownloadProgress:a,onUploadProgress:c,responseType:l,headers:u,withCredentials:f="same-origin",fetchOptions:h}=te(t);l=l?(l+"").toLowerCase():"text";let d,p=ne([r,i&&i.toAbortSignal()],s);const m=p&&p.unsubscribe&&(()=>{p.unsubscribe()});let w;try{if(c&&ue&&"get"!==n&&"head"!==n&&0!==(w=await(async(t,e)=>lt.toFiniteNumber(t.getContentLength())??(async t=>{if(null==t)return 0;if(lt.isBlob(t))return t.size;if(lt.isSpecCompliantForm(t)){const e=new Request(Nt.origin,{method:"POST",body:t});return(await e.arrayBuffer()).byteLength}return lt.isArrayBufferView(t)||lt.isArrayBuffer(t)?t.byteLength:(lt.isURLSearchParams(t)&&(t+=""),lt.isString(t)?(await ae(t)).byteLength:void 0)})(e))(u,o))){let t,n=new Request(e,{method:"POST",body:o,duplex:"half"});if(lt.isFormData(o)&&(t=n.headers.get("content-type"))&&u.setContentType(t),n.body){const[t,e]=Jt(w,Xt(Wt(c)));o=re(n.body,65536,t,e)}}lt.isString(f)||(f=f?"include":"omit");const r="credentials"in Request.prototype;d=new Request(e,{...h,signal:p,method:n.toUpperCase(),headers:u.normalize().toJSON(),body:o,duplex:"half",credentials:r?f:void 0});let i=await fetch(d,h);const s=fe&&("stream"===l||"response"===l);if(fe&&(a||s&&m)){const t={};["status","statusText","headers"].forEach((e=>{t[e]=i[e]}));const e=lt.toFiniteNumber(i.headers.get("content-length")),[n,o]=a&&Jt(e,Xt(Wt(a),!0))||[];i=new Response(re(i.body,65536,n,(()=>{o&&o(),m&&m()})),t)}l=l||"text";let b=await he[lt.findKey(he,l)||"text"](i,t);return!s&&m&&m(),await new Promise(((e,n)=>{Vt(e,n,{data:b,headers:qt.from(i.headers),status:i.status,statusText:i.statusText,config:t,request:d})}))}catch(e){if(m&&m(),e&&"TypeError"===e.name&&/Load failed|fetch/i.test(e.message))throw Object.assign(new ut("Network Error",ut.ERR_NETWORK,t,d),{cause:e.cause||e});throw ut.from(e,e&&e.code,t,d)}})};lt.forEach(pe,((t,e)=>{if(t){try{Object.defineProperty(t,"name",{value:e})}catch(t){}Object.defineProperty(t,"adapterName",{value:e})}}));const me=t=>"- "+t,we=t=>lt.isFunction(t)||null===t||!1===t,be=t=>{t=lt.isArray(t)?t:[t];const{length:e}=t;let n,o;const r={};for(let i=0;e>i;i++){let e;if(n=t[i],o=n,!we(n)&&(o=pe[(e=n+"").toLowerCase()],void 0===o))throw new ut(`Unknown adapter '${e}'`);if(o)break;r[e||"#"+i]=o}if(!o){const t=Object.entries(r).map((([t,e])=>`adapter ${t} `+(!1===e?"is not supported by the environment":"is not available in the build")));throw new ut("There is no suitable adapter to dispatch the request "+(e?t.length>1?"since :\n"+t.map(me).join("\n"):" "+me(t[0]):"as no adapter specified"),"ERR_NOT_SUPPORT")}return o};function ye(t){if(t.cancelToken&&t.cancelToken.throwIfRequested(),t.signal&&t.signal.aborted)throw new Ht(null,t)}function ve(t){return ye(t),t.headers=qt.from(t.headers),t.data=Bt.call(t,t.transformRequest),-1!==["post","put","patch"].indexOf(t.method)&&t.headers.setContentType("application/x-www-form-urlencoded",!1),be(t.adapter||Ut.adapter)(t).then((function(e){return ye(t),e.data=Bt.call(t,t.transformResponse,e),e.headers=qt.from(e.headers),e}),(function(e){return _t(e)||(ye(t),e&&e.response&&(e.response.data=Bt.call(t,t.transformResponse,e.response),e.response.headers=qt.from(e.response.headers))),Promise.reject(e)}))}const ge={};["object","boolean","number","function","string","symbol"].forEach(((t,e)=>{ge[t]=function(n){return typeof n===t||"a"+(1>e?"n ":" ")+t}}));const xe={};ge.transitional=function(t,e,n){function o(t,e){return"[Axios v1.10.0] Transitional option '"+t+"'"+e+(n?". "+n:"")}return(n,r,i)=>{if(!1===t)throw new ut(o(r," has been removed"+(e?" in "+e:"")),ut.ERR_DEPRECATED);return e&&!xe[r]&&(xe[r]=!0),!t||t(n,r,i)}},ge.spelling=function(t){return(t,e)=>!0};const Re={assertOptions:function(t,e,n){if("object"!=typeof t)throw new ut("options must be an object",ut.ERR_BAD_OPTION_VALUE);const o=Object.keys(t);let r=o.length;for(;r-- >0;){const i=o[r],s=e[i];if(s){const e=t[i],n=void 0===e||s(e,i,t);if(!0!==n)throw new ut("option "+i+" must be "+n,ut.ERR_BAD_OPTION_VALUE)}else if(!0!==n)throw new ut("Unknown option "+i,ut.ERR_BAD_OPTION)}},validators:ge},ke=Re.validators;class Oe{constructor(t){this.defaults=t||{},this.interceptors={request:new kt,response:new kt}}async request(t,e){try{return await this.l(t,e)}catch(t){if(t instanceof Error){let e={};Error.captureStackTrace?Error.captureStackTrace(e):e=Error();const n=e.stack?e.stack.replace(/^.+\n/,""):"";try{t.stack?n&&!(t.stack+"").endsWith(n.replace(/^.+\n.+\n/,""))&&(t.stack+="\n"+n):t.stack=n}catch(t){}}throw t}}l(t,e){"string"==typeof t?(e=e||{}).url=t:e=t||{},e=Qt(this.defaults,e);const{transitional:n,paramsSerializer:o,headers:r}=e;void 0!==n&&Re.assertOptions(n,{silentJSONParsing:ke.transitional(ke.boolean),forcedJSONParsing:ke.transitional(ke.boolean),clarifyTimeoutError:ke.transitional(ke.boolean)},!1),null!=o&&(lt.isFunction(o)?e.paramsSerializer={serialize:o}:Re.assertOptions(o,{encode:ke.function,serialize:ke.function},!0)),void 0!==e.allowAbsoluteUrls||(void 0!==this.defaults.allowAbsoluteUrls?e.allowAbsoluteUrls=this.defaults.allowAbsoluteUrls:e.allowAbsoluteUrls=!0),Re.assertOptions(e,{baseUrl:ke.spelling("baseURL"),withXsrfToken:ke.spelling("withXSRFToken")},!0),e.method=(e.method||this.defaults.method||"get").toLowerCase();let i=r&<.merge(r.common,r[e.method]);r&<.forEach(["delete","get","head","post","put","patch","common"],(t=>{delete r[t]})),e.headers=qt.concat(i,r);const s=[];let a=!0;this.interceptors.request.forEach((function(t){"function"==typeof t.runWhen&&!1===t.runWhen(e)||(a=a&&t.synchronous,s.unshift(t.fulfilled,t.rejected))}));const c=[];let l;this.interceptors.response.forEach((function(t){c.push(t.fulfilled,t.rejected)}));let u,f=0;if(!a){const t=[ve.bind(this),void 0];for(t.unshift.apply(t,s),t.push.apply(t,c),u=t.length,l=Promise.resolve(e);u>f;)l=l.then(t[f++],t[f++]);return l}u=s.length;let h=e;for(f=0;u>f;){const e=s[f++],n=s[f++];try{h=e(h)}catch(t){n.call(this,t);break}}try{l=ve(h)}catch(t){return Promise.reject(t)}for(f=0,u=c.length;u>f;)l=l.then(c[f++],c[f++]);return l}getUri(t){return Rt(Zt((t=Qt(this.defaults,t)).baseURL,t.url,t.allowAbsoluteUrls),t.params,t.paramsSerializer)}}lt.forEach(["delete","get","head","options"],(function(t){Oe.prototype[t]=function(e,n){return this.request(Qt(n||{},{method:t,url:e,data:(n||{}).data}))}})),lt.forEach(["post","put","patch"],(function(t){function e(e){return function(n,o,r){return this.request(Qt(r||{},{method:t,headers:e?{"Content-Type":"multipart/form-data"}:{},url:n,data:o}))}}Oe.prototype[t]=e(),Oe.prototype[t+"Form"]=e(!0)}));const Te=Oe;class Ee{constructor(t){if("function"!=typeof t)throw new TypeError("executor must be a function.");let e;this.promise=new Promise((function(t){e=t}));const n=this;this.promise.then((t=>{if(!n.u)return;let e=n.u.length;for(;e-- >0;)n.u[e](t);n.u=null})),this.promise.then=t=>{let e;const o=new Promise((t=>{n.subscribe(t),e=t})).then(t);return o.cancel=function(){n.unsubscribe(e)},o},t((function(t,o,r){n.reason||(n.reason=new Ht(t,o,r),e(n.reason))}))}throwIfRequested(){if(this.reason)throw this.reason}subscribe(t){this.reason?t(this.reason):this.u?this.u.push(t):this.u=[t]}unsubscribe(t){if(!this.u)return;const e=this.u.indexOf(t);-1!==e&&this.u.splice(e,1)}toAbortSignal(){const t=new AbortController,e=e=>{t.abort(e)};return this.subscribe(e),t.signal.unsubscribe=()=>this.unsubscribe(e),t.signal}static source(){let t;return{token:new Ee((function(e){t=e})),cancel:t}}}const Se=Ee,Ae={Continue:100,SwitchingProtocols:101,Processing:102,EarlyHints:103,Ok:200,Created:201,Accepted:202,NonAuthoritativeInformation:203,NoContent:204,ResetContent:205,PartialContent:206,MultiStatus:207,AlreadyReported:208,ImUsed:226,MultipleChoices:300,MovedPermanently:301,Found:302,SeeOther:303,NotModified:304,UseProxy:305,Unused:306,TemporaryRedirect:307,PermanentRedirect:308,BadRequest:400,Unauthorized:401,PaymentRequired:402,Forbidden:403,NotFound:404,MethodNotAllowed:405,NotAcceptable:406,ProxyAuthenticationRequired:407,RequestTimeout:408,Conflict:409,Gone:410,LengthRequired:411,PreconditionFailed:412,PayloadTooLarge:413,UriTooLong:414,UnsupportedMediaType:415,RangeNotSatisfiable:416,ExpectationFailed:417,ImATeapot:418,MisdirectedRequest:421,UnprocessableEntity:422,Locked:423,FailedDependency:424,TooEarly:425,UpgradeRequired:426,PreconditionRequired:428,TooManyRequests:429,RequestHeaderFieldsTooLarge:431,UnavailableForLegalReasons:451,InternalServerError:500,NotImplemented:501,BadGateway:502,ServiceUnavailable:503,GatewayTimeout:504,HttpVersionNotSupported:505,VariantAlsoNegotiates:506,InsufficientStorage:507,LoopDetected:508,NotExtended:510,NetworkAuthenticationRequired:511};Object.entries(Ae).forEach((([t,e])=>{Ae[e]=t}));const je=Ae,$e=function t(e){const n=new Te(e),o=g(Te.prototype.request,n);return lt.extend(o,Te.prototype,n,{allOwnKeys:!0}),lt.extend(o,n,null,{allOwnKeys:!0}),o.create=function(n){return t(Qt(e,n))},o}(Ut);$e.Axios=Te,$e.CanceledError=Ht,$e.CancelToken=Se,$e.isCancel=_t,$e.VERSION="1.10.0",$e.toFormData=bt,$e.AxiosError=ut,$e.Cancel=$e.CanceledError,$e.all=function(t){return Promise.all(t)},$e.spread=function(t){return function(e){return t.apply(null,e)}},$e.isAxiosError=function(t){return lt.isObject(t)&&!0===t.isAxiosError},$e.mergeConfig=Qt,$e.AxiosHeaders=qt,$e.formToJSON=t=>Pt(lt.isHTMLForm(t)?new FormData(t):t),$e.getAdapter=be,$e.HttpStatusCode=je,$e.default=$e;const Ne=$e,{Axios:Pe,AxiosError:Ce,CanceledError:Ue,isCancel:Fe,CancelToken:De,VERSION:Le,all:Ie,Cancel:ze,isAxiosError:Me,spread:qe,toFormData:Be,AxiosHeaders:_e,HttpStatusCode:He,formToJSON:Ve,getAdapter:Xe,mergeConfig:Je}=Ne,We=new class{constructor(){this.scopeAttribute="",this.scopeBody="",this.scopedKeyframes=new Map}parse(t,e){return this.scopeAttribute=`[vrefof="${e}"]`,this.scopeBody=`[vref="${e}"]`,this.scopedKeyframes.clear(),this.scopeSuffix=e.replace(/[^a-zA-Z0-9]/g,""),t=this.removeComments(t),this.collectKeyframes(t),this.parseRules(t)}collectKeyframes(t){const e=/@keyframes\s+([^\s{]+)/gi;let n;for(;null!==(n=e.exec(t));){const t=n[1],e=t+"-"+this.scopeSuffix;this.scopedKeyframes.set(t,e)}}removeComments(t){return t.replace(/\/\*[\s\S]*?\*\//g,"")}parseRules(t){let e="",n=0;for(;n=t.length)break;if("@"===t[n]){const o=this.parseAtRule(t,n);e+=o.content,n=o.endIndex}else{const o=this.parseNormalRule(t,n);e+=o.content,n=o.endIndex}}return e}parseAtRule(t,e){let n=e,o="";for(;n=t.length)return{content:o,endIndex:n};const r=o.toLowerCase().trim();if(r.startsWith("@keyframes"))return this.parseKeyframes(t,e);if(r.startsWith("@media"))return this.parseMedia(t,e);if(r.startsWith("@supports"))return this.parseSupports(t,e);{const e=this.findMatchingBrace(t,n);return{content:o+e.content,endIndex:e.endIndex}}}parseKeyframes(t,e){let n=e,o="";for(;n=t.length)return{content:o,endIndex:n};const r=this.findMatchingBrace(t,n),i=r.content,s=this.extractKeyframeName(o),a=this.scopedKeyframes.get(s);return a&&(o=o.replace(s,a)),o+=i,{content:o,endIndex:r.endIndex}}extractKeyframeName(t){const e=t.match(/@keyframes\s+([^\s{]+)/i);return e?e[1]:""}parseMedia(t,e){let n=e,o="";for(;n=t.length)return{content:o,endIndex:n};o+="{",n++;let r=1,i="";for(;n0;){if("{"===t[n])r++;else if("}"===t[n]&&(r--,0===r))break;i+=t[n],n++}return o+=this.parseRules(i),n=t.length)return{content:o,endIndex:n};const r=this.addScopeToSelector(o.trim()),i=this.findMatchingBrace(t,n);return{content:r+this.processRuleContent(i.content),endIndex:i.endIndex}}processRuleContent(t){let e=t;return e=e.replace(/animation\s*:\s*([^;]+);/gi,((t,e)=>`animation: ${this.processAnimationValue(e)};`)),e=e.replace(/animation-name\s*:\s*([^;]+);/gi,((t,e)=>`animation-name: ${this.processAnimationNames(e)};`)),e}processAnimationValue(t){return t.split(",").map((t=>t.trim())).map((t=>{const e=t.split(/\s+/);for(let n=0;n{const e=t.trim();return this.scopedKeyframes.get(e)||e})).join(", ")}addScopeToSelector(t){return t.trim()?t.split(",").map((t=>t.trim())).map((t=>this.addScopeToSingleSelector(t))).join(", "):t}addScopeToSingleSelector(t){if(!t.trim())return t;if(t.includes("::")){const e=t.split("::"),n=e[0],o="::"+e.slice(1).join("::");return this.addScopeToSelectorPart(n)+o}if(t.includes(":")&&!t.includes("::")){const e=t.match(/^([^:]+)(:.+)$/);if(e){const t=e[1],n=e[2];return this.addScopeToSelectorPart(t)+n}}return"*"===t||t.startsWith("@")?t:this.addScopeToSelectorPart(t)}addScopeToSelectorPart(t){const e=/(\s*[>+~]\s*|\s+)/;if(e.test(t)){const n=t.split(e);if(/^body(?:$|[:\[ ])/.test(n[0]))return n[0]=this.scopeBody+n[0].slice(4),n.join("");if(/^:root(?:$|[:\[ ])/.test(n[0]))return n[0]=this.scopeBody+n[0].slice(5),n.join("");for(let t=n.length-1;t>=0;t--)if(n[t].trim()&&!e.test(n[t])){let e=n[t].trim();n[t]=/^body(?:$|[:\[ ])/.test(e)?this.scopeBody+e.slice(4):/^:root(?:$:[$:\[ ])/.test(e)?this.scopeBody+e.slice(5):n[t].trim()+this.scopeAttribute;break}return n.join("")}let n=(t=t.trim()).trim();return/^body(?:$|[:\[ ])/.test(n)?this.scopeBody+n.slice(4):/^:root(?:$:[$:\[ ])/.test(n)?this.scopeBody+n.slice(5):n+this.scopeAttribute}findMatchingBrace(t,e){let n=e,o="",r=0;for(;n{this.removeMessage(s),i&&i()},s.appendChild(t)}return this.container.appendChild(s),setTimeout((()=>{s.classList.add("show")}),10),o>0&&setTimeout((()=>{this.removeMessage(s),i&&i()}),o),s}removeMessage(t){t&&t.parentNode&&(t.classList.remove("show"),setTimeout((()=>{t.parentNode&&t.parentNode.removeChild(t)}),300))}success(t,e={}){return this.createMessage("success",t,e)}warning(t,e={}){return this.createMessage("warning",t,e)}error(t,e={}){return this.createMessage("error",t,e)}info(t,e={}){return this.createMessage("info",t,e)}h(t,e={}){return new Promise(((n,o)=>{const{title:r="\u63d0\u793a",type:i="confirm",inputValue:s="",confirmText:a="\u786e\u5b9a",cancelText:c="\u53d6\u6d88",onConfirm:l=null,onCancel:u=()=>{n("")}}=e,f=document.createElement("div");f.className="prompt-overlay";const h=document.createElement("div");h.className="prompt-dialog";const d=document.createElement("div");d.className="prompt-header";const p=document.createElement("h3");p.className="prompt-title",p.textContent=r;const m=document.createElement("button");m.className="prompt-close",m.innerHTML="×",d.appendChild(p),d.appendChild(m);const w=document.createElement("div");w.className="prompt-body";const b=document.createElement("div");b.className="prompt-content",b.textContent=t,w.appendChild(b);let y=null;"input"===i&&(y=document.createElement("input"),y.className="prompt-input",y.type="text",y.value=s,w.appendChild(y));const v=document.createElement("div");v.className="prompt-footer";const g=document.createElement("button");g.className="prompt-btn prompt-btn-cancel",g.textContent=c;const x=document.createElement("button");x.className="prompt-btn prompt-btn-confirm",x.textContent=a,v.appendChild(g),v.appendChild(x),h.appendChild(d),h.appendChild(w),h.appendChild(v),f.appendChild(h),document.body.appendChild(f),setTimeout((()=>{f.classList.add("show")}),10),y&&setTimeout((()=>{y.focus()}),300);const R=(t=null)=>(f.classList.remove("show"),setTimeout((()=>{f.parentNode&&f.parentNode.removeChild(f)}),300),t);m.onclick=()=>{R(),u?u():o(Error("cancelled"))},g.onclick=()=>{R(),u?u():o(Error("cancelled"))},x.onclick=()=>{const t=!y||y.value;R(),n(t),l&&l(t)};const k=t=>{"Escape"===t.key&&(R(),u?u():o(Error("cancelled")),document.removeEventListener("keydown",k))};document.addEventListener("keydown",k),f.onclick=t=>{t.target===f&&(R(),u?u():o(Error("cancelled")))}}))}confirm(t,e={}){return this.h(t,{...e,type:"confirm"})}prompt(t,e,n={}){return this.h(t,{...n,type:"input",inputValue:e})}};var Ge={},Ze={};const Ye={};function Qe(t,e){Array.from(t.childNodes).forEach((t=>{1===t.nodeType&&(t.setAttribute("vrefof",e),Qe(t,e))}))}async function tn(t,e,n,o){void 0===n&&(n="#"+function(){let t=(new Date).getTime().toString(36);t.length>4&&(t=t.substring(t.length-4));let e="";for(let n=0;4>n;n++)e+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".charAt(Math.floor(52*Math.random()));return e+t.padStart(4,"0")}()),n.endsWith(".html")&&(n=n.slice(0,-5));let r=(new DOMParser).parseFromString(t,"text/html");if(r.body.hasAttribute("root")&&!o)throw Error("HTTP error! status: 404");let i={url:n,heads:[],body:document.createElement("div"),setup:void 0,scripts:[],styles:"",txt:t,env:e,tmp:r,customAttrs:{}};if(i.heads=Array.from(r.querySelector("head")?.children),n&&(r.querySelectorAll("style").forEach((t=>{null===t.getAttribute("unscoped")?i.styles+=We.parse(t.innerHTML,n):i.styles+=t.innerHTML})),i.styles)){const t=document.createElement("style");t.innerHTML=i.styles,t.setAttribute("vref",n),document.head.appendChild(t)}return i.body.append(...r.querySelector("body").childNodes),i.body.querySelectorAll("script").forEach((t=>{""!=t.innerHTML.trim()?(t.hasAttribute("setup")?i.setup=t:t.hasAttribute("no-vhtml")||i.scripts.push(t),t.remove()):t.remove()})),Array.from(r.body.attributes).forEach((t=>{/^[a-zA-Z]/.test(t.name)?i.body.setAttribute(t.name,t.value):i.customAttrs[t.name]=t.value})),i.body.setAttribute("vref",n),Qe(i.body,n),o||await async function(t,e){for(let n of t.heads){let o=n.nodeName.toLowerCase();"link"===o?nn(n,e):"script"===o?await en(n,e):"title"===o&&(t.title=n.innerText)}}(i,e),i}function en(t,e){let n=t.getAttribute("src"),o=t.getAttribute("key"),r=e?.root;if(r&&n.startsWith("/")&&(n=r+n),n.startsWith("@")&&(n=n.slice(1)),n&&document.querySelector(`script[src="${n}"]`))return;if(o&&document.querySelector(`script[key="${o}"]`))return;let i=document.createElement("script");return i.src=n,i.key=o,i.type=t.getAttribute("type")||"text/javascript",new Promise(((t,e)=>{i.onload=()=>{t(i)},i.onerror=()=>e(Error("Failed to load script "+n)),document.head.appendChild(i)}))}async function nn(t,e){let n=t.getAttribute("href"),o=t.getAttribute("key"),r=e?.root;r&&n.startsWith("/")&&(n=r+n),n.startsWith("@")&&(n=n.slice(1)),n&&document.querySelector(`link[href="${n}"]`)||o&&document.querySelector(`link[key="${o}"]`)||(t.setAttribute("href",n),document.head.append(t))}const on={FetchUI:async function(t,e,n){t&&"/"!==t||(t="/root.html"),t.startsWith("http")||t.startsWith("@")||t.startsWith("/")||(t="/"+t);let o=e?.root;if(o&&t.startsWith("/")&&(t=o+t),t.startsWith("@")&&(t=t.slice(1)),Ge[t])return Promise.resolve(Ge[t]);if(Ze[t])return Ze[t];let r={};const i=fetch(t+"?random="+Math.random()).then((async e=>{if(!e.ok)throw Error("HTTP error! status: "+e.status);for(const[t,i]of e.headers.entries())t.startsWith("vhtml-")&&(r[t.slice(5)]=i);let n=r.root||"";t.startsWith("http")&&(n=new URL(t).origin+n,r.root=n);let o=await async function(t,e){if(!Ye[t=t||""]){let n=t.startsWith("http")?t:window.location.origin+t;Ye[t]=Object.assign({},e,{root:t,$G:y.Wrap({}),$bus:new v,$axios:Ne.create({baseURL:n}),$message:Ke,$router:null,$emit:null}),t===$vhtml.root||null===$vhtml.root?Ye[t].$router=$vhtml.$router:Ye[t].$router={addRoutes:()=>{},beforeEnter:()=>{}};try{await(await import(n+"/env.js")).default(Ye[t])}catch(g){}}return Ye[t]}(n,r);return Object.assign(r,o),e.text()})).then((e=>tn(e,r,t,n))).then((e=>(Ge[t]=e,e))).catch((e=>{e.message;let n=document.createElement("div");n.style.cssText="\n backgound:#aaa;\n height:100%;\n width: 100%;\n display:grid;\n place-items: center;\n",n.innerHTML=`\n
\n
404
\n

${t}

\n
\n`;let o={heads:[],body:n,setup:"",scripts:[],styles:"",txt:"",tmp:"",env:r,err:e};return Ge[t]=o,o})).finally((()=>{delete Ze[t]}));return Ze[t]=i,i},FetchFile:async function(t){return fetch(t).then((t=>{if(!t.ok)throw Error("HTTP error! status: "+t.status);return t.text()}))},LoadScript:en,LoadLink:nn,ParseUI:tn};function rn(t,e){let n,o;if(t.startsWith("http://")||t.startsWith("https://")){if(n=new URL(t),n.origin!==window.location.origin)return null;n.pathname.startsWith(e)&&(o=n.pathname.slice(e.length))}else n=new URL(t,window.location.href),o=n.pathname;const r={};return n.searchParams.forEach(((t,e)=>{r[e]=t})),{path:o,query:r,hash:n.hash}}class sn{constructor(t,e){this.originalPath=t,this.name=e,this.keys=[],this.regexp=this.pathToRegexp(t)}pathToRegexp(t){let e=t.replace(/:([^(/]+)/g,((t,e)=>(this.keys.push(e),`(?<${e}>[^/]+)`)));return e=e.replace(/\*(\w+)/g,((t,e)=>(this.keys.push(e),`(?<${e}>.*)`))),e=e.replace(/\*/g,".*"),RegExp(`^${e}$`)}match(t){let e;if("string"==typeof t)e=t;else{if(!t||"object"!=typeof t)return null;if(!t.path)return t.name&&t.name===this.name?{path:this.originalPath,params:t.params||{},matched:this.originalPath}:null;e=t.path}const n=this.regexp.exec(e);if(!n)return null;const o={};return this.keys.forEach((t=>{n.groups?.[t]&&(o[t]=n.groups[t])})),{path:this.originalPath,params:o,matched:n[0]}}}const an=new Map;class cn{constructor(t,e,n){this.vhtml=t,this.node=e,this.layoutDom=void 0,this.matchedRoute=n,this.htmlPath=this.resolveHtmlPath(n)}resolveHtmlPath(t){let e=t.route.component||t.route.path;return"function"==typeof e&&(e=e(t.path)),Object.entries(t.params).forEach((([t,n])=>{e=e.replace(":"+t,n)})),e.startsWith("/")||(e="/"+e),e.endsWith("/")&&(e=e.slice(0,-1)),e.endsWith(".html")||(e+=".html"),e}async mount(t,e,n){const o=await on.FetchUI(this.htmlPath,t);if(o.err){let n=document.createElement("div");return Object.assign(n.style,{width:"100%",height:"100%"}),n.append(...e),this.node.innerHTML="",this.node.append(n),void this.vhtml.parseRef(this.htmlPath,n,{},t,null,!0)}this.title=o.title||"";const r={},i=document.createElement("div");if(i.setAttribute("vsrc",this.htmlPath),r[""]=[i],this.slots=r,!n)return this.node.innerHTML="",this.node.append(i),void this.vhtml.parseRef(this.htmlPath,i,{},t,null);let s=an.get(n);if(s)this.layoutDom=s,this.activate();else{let e=n;e.startsWith("/")||(e="/"+n),e.endsWith(".html")||(e+=".html"),e.startsWith("/layout")||(e="/layout"+e);const o=await on.FetchUI(e,t);if(o.err)return this.node.innerHTML="",this.node.append(i),void this.vhtml.parseRef(this.htmlPath,i,{},t,null);s=o.body.cloneNode(!0),an.set(n,s),i.$refData=y.Wrap({}),s.$refSlots=y.Wrap({...r}),this.node.innerHTML="",this.node.append(s),this.layoutDom=s,this.vhtml.parseRef("/layout/"+n,s,{},t,null,!0)}}activate(){this.title&&(document.title=this.title);const t=this.layoutDom;if(t)t.querySelectorAll("vslot").forEach((e=>{e.closest("[vref]")===t&&this.slots[e.getAttribute("name")||""]&&(e.innerHTML="")})),Object.keys(t.$refSlots).forEach((e=>{delete t.$refSlots[e]})),Object.assign(t.$refSlots,this.slots),t.isConnected||(this.node.innerHTML=""),this.node.append(t);else{this.node.innerHTML="";const t=this.slots[""];t instanceof Array?this.node.append(...t):this.node.append(t)}}}const ln=new class{#t=[];#e=[];#n=null;#o="";#r=[];#i=new Map;#s=null;#a=null;#c=[];#l=!1;#u=null;#f=new Map;constructor(){this.init()}get routes(){return this.#t.slice()}get history(){return this.#e.slice()}get current(){return this.#n}get query(){return this.#n?.query||{}}get params(){return this.#n?.params||{}}get root(){return this.#o}onChange(t){this.#r.push(t)}addRoute(t){if(!t.path)throw Error("Route must have a path");"/"!=t.path&&t.path.endsWith("/")&&(t.path=t.path.slice(0,-1));const e={path:t.path,component:t.component,name:t.name,meta:t.meta||{},children:t.children||[],matcher:new sn(t.path,t.name),description:t.description||"",layout:t.layout||""};this.#t.push(e),t.name&&this.#f.set(t.name,e),t.children?.length>0&&t.children.forEach((n=>{const o=t.path+(n.path.startsWith("/")?n.path:"/"+n.path),r=n.layout||t.layout||"",i={...t.meta,...n.meta};this.addRoute({...n,path:o,parent:e,layout:r,meta:i})}))}addRoutes(t){t.forEach((t=>this.addRoute(t)))}#h(t,e){this.#r.forEach((n=>{if("function"==typeof n)try{n(t,e)}catch(o){}}))}#d(t){const e=this.#n;this.#n={path:t.path,fullPath:t.fullPath,params:t.params||{},query:t.query||{},hash:new URL(t.fullPath,window.location.origin).hash,meta:t.route?.meta||{},description:t.route?.description||"",layout:t.route?.layout||"",name:t.route?.name,matched:t.route?[t.route]:[]},this.#e.push(this.#n),this.#o&&!t.fullPath.startsWith("http")?history.pushState({},"",this.#o+t.fullPath):history.pushState({},"",t.fullPath),this.#h(this.#n,e)}matchRoute(t){const e=this.normalizeRouteTarget(t);if(!e)return null;const{path:n,query:o,params:r,name:i}=e;if(i){const t=this.#f.get(i);if(!t)return null;let e=t.path;Object.entries(r).forEach((([t,n])=>{e=e.replace(":"+t,n)}));const n=t.matcher.match(e);return n?{route:t,params:{...n.params,...r},matched:n.matched,path:e,query:o,name:i}:null}for(const s of this.#t){const t=s.matcher.match(n);if(t&&s.component)return{route:s,params:{...t.params,...r},matched:t.matched,description:s.description,layout:s.layout,path:n,query:o,name:s.name}}return null}normalizeRouteTarget(t){let e,n,o={},r={},i="";if("string"==typeof t){const n=rn(t,this.#o);if(!n)return null;e=n.path,o={...n.query},i=n.hash}else{if(!t||"object"!=typeof t)return null;if(t.path){const n=rn(t.path,this.#o);if(!n)return null;e=n.path,o={...n.query,...t.query||{}},i=t.hash||n.hash,r=t.params||{}}else{if(!t.name)return null;n=t.name,o=t.query||{},r=t.params||{},i=t.hash||""}}return e&&!e.startsWith("/")&&(e="/"+e),this.#o&&(e=e.startsWith(this.#o)?e.slice(this.#o.length):e),e.startsWith("/")||(e="/"+e),"/"!=e&&e.endsWith("/")&&(e=e.slice(0,-1)),{path:e,query:o,params:r,hash:i,name:n}}matchTo(t){const e=this.matchRoute(t);if(!e)return null;const{route:n,params:o,query:r,path:i,name:s}=e;let a="";r&&Object.keys(r).length>0&&(a="?"+Object.entries(r).map((([t,e])=>`${encodeURIComponent(t)}=${encodeURIComponent(e)}`)).join("&"));const c=(i||e.path)+a;return{route:n,params:o,query:r,name:s||n.name,path:i||e.path,fullPath:c,matched:[n]}}buildUrl(t,e={}){const n=new URL(t,window.location.origin);return Object.entries(e).forEach((([t,e])=>{n.searchParams.append(t,e)})),n}resolveRoutePath(t,e={}){let n=t.component||t.path;return Object.entries(e).forEach((([t,e])=>{n=n.replace(":"+t,e)})),"/"!==n&&""!==n||(n="/index"),n.startsWith("/")||(n="/"+n),n.endsWith(".html")&&(n=n.slice(0,-5)),n.endsWith("/")&&(n=n.slice(0,-1)),n}async#p(t){if(!t)return;const{route:e,params:n,query:o}=t,r={path:t.path,fullPath:t.fullPath,params:n,query:o,hash:new URL(t.fullPath,window.location.origin).hash,meta:e.meta,description:e.description,layout:e.layout,name:e.name,matched:[e]};if(this.beforeEnter)try{let t=!0;if(!1===await this.beforeEnter(r,this.#n,(e=>{e&&(t=!1,this.push(e))}))||!t)return}catch(a){return}const i=t.fullPath;let s=this.#i.get(i);this.#d(t),s?s.activate():(s=new cn(this.#u,this.#s,t),await s.mount(this.#a,this.#c,r.layout),this.#i.set(i,s))}async push(t){const e=this.matchTo(t);e?await this.#p(e):"string"==typeof t||t.path||t.name}replace(t){this.push(t),this.#e.length>1&&this.#e.splice(-2,1)}go(t){history.go(t)}back(){history.back()}forward(){history.forward()}init(){this.#l||(this.#l=!0,document.body.addEventListener("click",(t=>{const e=t.target.closest("a");if(!e)return;const n=e.getAttribute("href");!n||n.startsWith("http")||n.startsWith("#")||(t.preventDefault(),e.hasAttribute("reload")?window.location.href=n:this.push(n))}),!0),window.addEventListener("popstate",(()=>{this.push(window.location.href)})))}ParseVrouter(t,e,n){this.#s=e,this.#a=n,this.#o=n.root||"",this.#c=Array.from(e.childNodes),this.#u=t,this.push(window.location.href)}},un={$router:ln},fn=[];document.addEventListener("click",(t=>{fn.forEach((e=>{e?.dom instanceof Element&&"function"==typeof e?.callback&&(e.dom.contains(t.target)||e.callback(t))}))}));const hn={CamelToKebabCase:function(t){return 0===t.length?"":t.charAt(0).toLowerCase()+t.slice(1).replace(/([A-Z])/g,(function(t,e){return"-"+e.toLowerCase()}))},EventsList:["load","unload","beforeunload","resize","scroll","submit","reset","input","change","focus","blur","keydown","keypress","keyup","click","dblclick","contextmenu","mousedown","mouseup","mousemove","mouseover","mouseout","mouseenter","mouseleave","touchstart","touchmove","touchend","touchcancel","drag","dragstart","dragend","dragover","dragenter","dragleave","drop","copy","cut","paste","animationstart","animationend","animationiteration","transitionend","abort","error","loadstart","progress","play","pause","ended","volumechange","timeupdate","loadeddata","waiting","playing","online","offline","storage","visibilitychange"],BindInputDomValue:function(t,e,n,o){const r="string"==typeof t?document.querySelector(t):t;if(r){switch(r.type||r.tagName.toLowerCase()){case"text":case"password":case"email":case"tel":case"url":case"search":case"number":case"range":case"color":case"date":case"time":case"datetime-local":case"month":case"week":case"hidden":case"textarea":o((()=>e[n]),(t=>{r.value=void 0===t?"":t})),r.addEventListener("input",(function(){e[n]=this.value}));break;case"checkbox":o((function(){r.checked=!!e[n]})),r.addEventListener("change",(function(){e[n]=this.checked}));break;case"radio":o((()=>{r.checked=r.value===e[n]})),r.addEventListener("change",(function(){this.checked&&(e[n]=this.value)}));break;case"select-one":case"select-multiple":o((()=>{let t=e[n];if(r.multiple){const e=Array.isArray(t)?t:[];for(let t=0;t{if("outer"===e){let e=fn.length;return fn.push({dom:t,callback:n}),()=>{fn[e]=null}}}},dn=async t=>navigator.clipboard&&navigator.clipboard.writeText?navigator.clipboard.writeText(t):(prompt("http\u73af\u5883\u65e0\u6cd5\u81ea\u52a8\u590d\u5236\uff0c\u8bf7\u624b\u52a8\u590d\u5236\u5185\u5bb9\u5230\u526a\u8d34\u677f:",t),new Promise((t=>{})));class pn{postMessage=(t,e)=>{};constructor(t={}){this.options={highlightColor:"#007bff",overlayColor:"rgba(0, 123, 255, 0.1)",borderWidth:"2px",zIndex:1e4,showTagName:!0,...t},this.isActive=!1,this.selectedElement=null,this.currentHoverElement=null,this.overlay=null,this.selectedOverlay=null,this.tooltip=null,this.selectedTooltip=null,this.actionPanel=null,this.originalCursor="",this.init()}init(){this.createStyles(),this.bindEvents()}createStyles(){const t=document.createElement("style");t.textContent=`\n .div-selector-overlay {\n position: fixed;\n pointer-events: none;\n border: ${this.options.borderWidth} solid ${this.options.highlightColor};\n background: ${this.options.overlayColor};\n z-index: ${this.options.zIndex};\n transition: all 0.2s ease;\n box-sizing: border-box;\n }\n \n .div-selector-selected {\n position: fixed;\n pointer-events: none;\n border: ${this.options.borderWidth} solid #28a745;\n background: rgba(40, 167, 69, 0.1);\n z-index: ${this.options.zIndex-1};\n box-sizing: border-box;\n }\n \n .div-selector-tooltip {\n position: fixed;\n background: rgba(51, 51, 51, 0.95);\n cursor:pointer;\n color: white;\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: 'Consolas', 'Monaco', 'Courier New', monospace;\n z-index: ${this.options.zIndex+1};\n user-select: none;\n box-shadow: 0 2px 8px rgba(0,0,0,0.3);\n border: 1px solid rgba(255,255,255,0.1);\n backdrop-filter: blur(4px);\n }\n \n .div-selector-tooltip.hover {\n background: rgba(0, 123, 255, 0.9);\n }\n \n .div-selector-tooltip.selected {\n background: rgba(40, 167, 69, 0.9);\n border-color: rgba(40, 167, 69, 0.3);\n }\n \n .div-selector-actions {\n position: fixed;\n background: white;\n border: 1px solid #ddd;\n border-radius: 8px;\n padding: 8px;\n z-index: ${this.options.zIndex+2};\n box-shadow: 0 4px 16px rgba(0,0,0,0.15);\n display: flex;\n gap: 6px;\n min-width: 30px;\n backdrop-filter: blur(8px);\n }\n \n .div-selector-btn {\n padding: 4px 6px;\n border: 1px solid #ddd;\n background: white;\n border-radius: 6px;\n cursor: pointer;\n font-size: 12px;\n transition: all 0.2s ease;\n text-align: left;\n white-space: nowrap;\n }\n \n .div-selector-btn:hover {\n background: #f8f9fa;\n transform: translateX(2px);\n }\n \n .div-selector-btn.danger {\n color: #dc3545;\n border-color: #dc3545;\n }\n \n .div-selector-btn.danger:hover {\n background: #dc3545;\n color: white;\n }\n \n .div-selector-btn.primary {\n background: #007bff;\n color: white;\n border-color: #007bff;\n }\n \n .div-selector-btn.primary:hover {\n background: #0056b3;\n }\n \n .div-selector-active {\n cursor: crosshair !important;\n }\n `,document.head.appendChild(t)}bindEvents(){this.handleMouseMove=this.handleMouseMove.bind(this),this.handleClick=this.handleClick.bind(this),this.handleScroll=this.handleScroll.bind(this),this.handleResize=this.handleResize.bind(this)}activate(){this.isActive||(this.isActive=!0,this.originalCursor=document.body.style.cursor,document.body.classList.add("div-selector-active"),document.addEventListener("mousemove",this.handleMouseMove),document.addEventListener("click",this.handleClick),window.addEventListener("scroll",this.handleScroll),window.addEventListener("resize",this.handleResize),this.createOverlay(),this.createTooltip())}deactivate(){this.isActive&&(this.isActive=!1,document.body.style.cursor=this.originalCursor,document.body.classList.remove("div-selector-active"),document.removeEventListener("mousemove",this.handleMouseMove),document.removeEventListener("click",this.handleClick),window.removeEventListener("scroll",this.handleScroll),window.removeEventListener("resize",this.handleResize),this.removeOverlay(),this.removeTooltip())}handleMouseMove(t){if(!this.isActive)return;const e=document.elementFromPoint(t.clientX,t.clientY);if(!e)return;if(this.isPluginElement(e))return;const n="DIV"===e.tagName?e:e.closest("div,[vref]");n&&!this.isPluginElement(n)&&this.selectedElement!==n&&(this.currentHoverElement=n,this.highlightElement(n),this.updateHoverTooltip(n))}handleClick(t){if(!this.isActive)return;const e=document.elementFromPoint(t.clientX,t.clientY);if(!e)return;if(this.isPluginElement(e))return;t.preventDefault(),t.stopPropagation();const n="DIV"===e.tagName?e:e.closest("div");n&&!this.isPluginElement(n)&&(this.selectElement(n),this.deactivate())}handleScroll(){this.selectedElement&&(this.updateSelectedOverlay(),this.updateSelectedTooltip(),this.updateActionPanelPosition()),this.currentHoverElement&&!this.selectedElement&&(this.highlightElement(this.currentHoverElement),this.updateHoverTooltip(this.currentHoverElement))}handleResize(){this.selectedElement&&(this.updateSelectedOverlay(),this.updateSelectedTooltip(),this.updateActionPanelPosition())}isPluginElement(t){return t.closest(".div-selector-overlay, .div-selector-selected, .div-selector-tooltip, .div-selector-actions")}createOverlay(){this.overlay=document.createElement("div"),this.overlay.className="div-selector-overlay",this.overlay.style.display="none",document.body.appendChild(this.overlay)}createSelectedOverlay(){this.selectedOverlay=document.createElement("div"),this.selectedOverlay.className="div-selector-selected",document.body.appendChild(this.selectedOverlay)}createTooltip(){this.tooltip=document.createElement("div"),this.tooltip.className="div-selector-tooltip hover",this.tooltip.style.display="none",document.body.appendChild(this.tooltip)}createSelectedTooltip(){this.selectedTooltip=document.createElement("div"),this.selectedTooltip.className="div-selector-tooltip selected",document.body.appendChild(this.selectedTooltip)}highlightElement(t){if(!this.overlay)return;const e=t.getBoundingClientRect();this.overlay.style.display="block",this.overlay.style.left=e.left+"px",this.overlay.style.top=e.top+"px",this.overlay.style.width=e.width+"px",this.overlay.style.height=e.height+"px"}updateHoverTooltip(t){if(!this.tooltip)return;const e=this.getElementInfo(t),n=t.getBoundingClientRect();this.tooltip.textContent=e,this.tooltip.style.display="block";let o=n.left-8,r=n.top-this.tooltip.offsetHeight-8;0>o&&(o=8),0>r&&(r=n.top+8),this.tooltip.style.left=o+"px",this.tooltip.style.top=r+"px"}selectElement(t){this.clearSelection(),this.selectedElement=t,this.createSelectedOverlay(),this.createSelectedTooltip(),this.updateSelectedOverlay(),this.updateSelectedTooltip(),this.overlay&&(this.overlay.style.display="none"),this.tooltip&&(this.tooltip.style.display="none"),this.showActionPanel()}updateSelectedOverlay(){if(!this.selectedOverlay||!this.selectedElement)return;const t=this.selectedElement.getBoundingClientRect();this.selectedOverlay.style.left=t.left+"px",this.selectedOverlay.style.top=t.top+"px",this.selectedOverlay.style.width=t.width+"px",this.selectedOverlay.style.height=t.height+"px"}updateSelectedTooltip(){if(!this.selectedTooltip||!this.selectedElement)return;const t=this.getElementInfo(this.selectedElement);let e=this.getFilePath(this.selectedElement);const n=this.selectedElement.getBoundingClientRect();this.selectedTooltip.addEventListener("click",(t=>{e&&this.postMessage("fs-open",e),t.preventDefault(),t.stopPropagation()})),this.selectedTooltip.textContent="\u2713 "+t;let o=n.left-8,r=n.top-this.selectedTooltip.offsetHeight-8;0>o&&(o=8),0>r&&(r=n.top+8),this.selectedTooltip.style.left=o+"px",this.selectedTooltip.style.top=r+"px"}showActionPanel(){this.removeActionPanel();const t=this.selectedElement.getBoundingClientRect();this.actionPanel=document.createElement("div"),this.actionPanel.className="div-selector-actions";let e=t.right-180,n=t.top+6;e+180>window.innerWidth&&(e=t.left-180-8),0>e&&(e=8),n+40>window.innerHeight&&(n=window.innerHeight-40-8),0>n&&(n=8),this.actionPanel.style.left=e+"px",this.actionPanel.style.top=n+"px",[{text:"\ud83d\udccb",action:()=>this.copySelector(this.selectedElement)},{text:"x",action:()=>this.clearSelection()}].forEach((t=>{const e=document.createElement("button");e.className="div-selector-btn "+(t.class||""),e.textContent=t.text,e.onclick=t.action,this.actionPanel.appendChild(e)})),document.body.appendChild(this.actionPanel)}updateActionPanelPosition(){if(!this.actionPanel||!this.selectedElement)return;const t=this.selectedElement.getBoundingClientRect(),e=this.actionPanel.offsetWidth,n=this.actionPanel.offsetHeight;let o=t.right-e+8,r=t.top-8;o+e>window.innerWidth&&(o=t.left-e-8),0>o&&(o=8),r+n>window.innerHeight&&(r=window.innerHeight-n-8),0>r&&(r=8),this.actionPanel.style.left=o+"px",this.actionPanel.style.top=r+"px"}clearSelection(){this.selectedElement=null,this.selectedOverlay&&(this.selectedOverlay.remove(),this.selectedOverlay=null),this.selectedTooltip&&(this.selectedTooltip.remove(),this.selectedTooltip=null),this.removeActionPanel()}getElementInfo(t){const e=t.getBoundingClientRect();let n=t.getAttribute("vref");return n||(n=t.closest("[vref]").getAttribute("vref"),n+="."+t.tagName.toLowerCase()),`${n} (${Math.round(e.width)}\xd7${Math.round(e.height)})`}getFilePath(t){let e=t.getAttribute("vref");return e||(e=t.closest("[vref]").getAttribute("vref")),e&&(e="/ui"+e+".html"),e}copySelector(t){let e=this.getFilePath(t);dn(e).then((()=>{this.showNotification("\ud83d\udccb CSS\u9009\u62e9\u5668\u5df2\u590d\u5236\u5230\u526a\u8d34\u677f")}))}copyXPath(t){const e=this.generateXPath(t);dn(e).then((()=>{this.showNotification("\ud83d\udd0d XPath\u5df2\u590d\u5236\u5230\u526a\u8d34\u677f")}))}viewStyles(t){const e=window.getComputedStyle(t);let n="\ud83d\udcca \u91cd\u8981\u6837\u5f0f\u5c5e\u6027:\n\n";["display","position","width","height","margin","padding","background-color","color","font-size","border","z-index","opacity"].forEach((t=>{n+=`${t}: ${e.getPropertyValue(t)}\n`})),alert(n)}showNotification(t){const e=document.createElement("div");e.style.cssText=`\n position: fixed;\n top: 20px;\n right: 20px;\n background: linear-gradient(135deg, #28a745, #20c997);\n color: white;\n padding: 12px 18px;\n border-radius: 8px;\n z-index: ${this.options.zIndex+10};\n font-size: 14px;\n box-shadow: 0 4px 12px rgba(0,0,0,0.2);\n transform: translateX(100%);\n transition: transform 0.3s ease;\n `,e.textContent=t,document.body.appendChild(e),setTimeout((()=>{e.style.transform="translateX(0)"}),100),setTimeout((()=>{e.style.transform="translateX(100%)",setTimeout((()=>{e.remove()}),300)}),2500)}generateXPath(t){if(t.id)return`//*[@id="${t.id}"]`;const e=[];for(;t&&t.nodeType===Node.ELEMENT_NODE;){let n=0,o=!1,r=!1;for(let e=t.previousSibling;e;e=e.previousSibling)e.nodeType===Node.ELEMENT_NODE&&e.nodeName===t.nodeName&&(r=!0,n++);for(let e=t.nextSibling;e&&!o;e=e.nextSibling)e.nodeType===Node.ELEMENT_NODE&&e.nodeName===t.nodeName&&(o=!0);const i=t.nodeName.toLowerCase(),s=r||o?`[${n+1}]`:"";if(e.unshift(i+s),(t=t.parentNode)===document.body)break}return e.length?"/"+e.join("/"):null}removeOverlay(){this.overlay&&(this.overlay.remove(),this.overlay=null)}removeTooltip(){this.tooltip&&(this.tooltip.remove(),this.tooltip=null)}removeActionPanel(){this.actionPanel&&(this.actionPanel.remove(),this.actionPanel=null)}}let mn=!1,wn=null;const bn=(t,e)=>{mn&&("string"!=typeof e&&"number"!=typeof e||(e={value:e}),window.parent.postMessage(Object.assign({type:t,from:"vdev"},e),"*"))};!async function(){const t=document.createElement("style");t.innerHTML="\n [vref] {\n display: block;\n }\n [vparsing] {\n display: none;\n -webkit-text-fill-color: transparent;\n }\n vslot, vrouter {\n display: block;\n }\n",document.head.firstChild?document.head.insertBefore(t,document.head.firstChild):document.head.appendChild(t);const e=[],n=t=>{if(!t.isConnected)return;let n=t.getAttribute("vdelay");if(n){let o=e[n];o&&o(t)}};function o(t,e){const n=Function("sandbox",t=`with (sandbox) { ${t} }`);let o={data:null,key:null};const r=t=>new Proxy(t,{has:(t,e)=>!0,get(t,e,n){if(e===Symbol.unscopables)return;let i=Reflect.get(t,e,n);return o.data=t,o.key=e,"object"==typeof i&&i?r(i):i},set:(t,e,n,o)=>!1});return n(r(e)),o}new MutationObserver((function(t,e){t.forEach((function(t){for(let e of t.addedNodes)1===e.nodeType&&(n(e),e.querySelectorAll("*[vdelay]").forEach(n))}))})).observe(document.body,{attributes:!1,childList:!0,subtree:!0,characterData:!1});const r=/{{|}}/g,i=/^(\s*(\w+)\s+in\s+|\((\w+),\s*(\w+)\)\s+in\s+)([\w\?\$\.\[\]\(\)'"]+)$/;window.$vhtml||(window.$vhtml=new class{app=null;root=null;vget=on;vproxy=y;t=!0;$router=un.$router;constructor(t){"string"==typeof t?this.app=document.getElementById(t):t instanceof HTMLElement?this.app=t:this.app=document.body,this.app&&(async()=>{let t=await on.FetchUI(window.location.pathname,{},!0);this.root=t.env?.root||"",t.env?.vdev&&window.self!==window.top&&(mn||(mn=!0,wn=new pn,bn("iframe-loaded"),wn.postMessage=bn,window.addEventListener("keyup",(t=>{"Escape"===t.key&&bn("key-esc")})),setTimeout((()=>{window.$vhtml&&window.$vhtml.$router&&$vhtml.$router.onChange((t=>{bn("url-change",t.fullPath)}))}),100),window.addEventListener("message",(t=>{const e=t.data;if("vhtml"==e.from)switch(e.type){case"reload":window.location.reload();break;case"magic":wn&&wn.isActive?wn.deactivate():wn&&wn.activate()}})))),this.parseRef("root",this.app,{},t.env||{},t,!0)})()}async parseDom(t,e={},n){if(n instanceof HTMLElement)throw Error("env error");let o=t.nodeName.toLowerCase();if(3===t.nodeType)return void this.parseTextNode(t,e,n);if(8===t.nodeType)return;if(1!==t.nodeType)return;if(t.hasAttribute("no-vhtml")||t.vparsed)return;let r=t.getAttribute("v-for");if(null!==r)return void this.parseVfor(r,t,e,n);if(-1!==o.indexOf("-")){let r="/"+o.split("-").join("/"),i=t.hasAttribute("single");return this.parseRef(r,t,e,n,null,i),void(t.vparsed=!0)}if(t.getAttribute(":vsrc")){let o=t.getAttribute(":vsrc");t.removeAttribute(":vsrc");let r=Array.from(t.attributes).map((t=>({name:t.name,value:t.value}))),i=Array.from(t.childNodes);return void y.Watch((()=>{delete t.vparsed,t.setAttribute("vparsing","");let s=y.Run(o,e,n);s&&(Array.from(t.attributes).forEach((e=>{t.removeAttribute(e.name)})),t.innerHTML="",r.forEach((e=>{t.setAttribute(e.name,e.value)})),i.forEach((e=>{t.appendChild(e.cloneNode(!0))})),this.parseRef(s,t,e,n,null,!1),t.vparsed=!0)}))}if(t.getAttribute("vsrc")){let o=t.hasAttribute("single");return this.parseRef(t.getAttribute("vsrc"),t,e,n,null,o),void(t.vparsed=!0)}if("div"===o&&t.getAttribute("v-html")){let o=t.getAttribute("v-html");return t.removeAttribute("v-html"),t.innerHTML="",this.parseAttrs(t,e,n),t.vparsed=!0,void y.Watch((()=>{let r=y.Run(o,e,n);t.innerHTML=r;let i=this.parseVif(Array.from(t.childNodes),e,n);for(let t of i)this.parseDom(t,e,n)}))}if("vslot"===o)return this.parseSlots(t,e,n),void(t.vparsed=!0);if("vrouter"===o)return this.parseAttrs(t,e,n),void un.$router.ParseVrouter(this,t,n);this.parseAttrs(t,e,n);let i=this.parseVif(Array.from(t.childNodes),e,n);for(let s of i)this.parseDom(s,e,n);t.vparsed=!0}onMountedRun(t,n,o=!0){if(o){if(t.isConnected)return void n(t);let o=e.push((t=>{t.removeAttribute("vdelay"),n(t)}));return void t.setAttribute("vdelay",o-1)}t.isConnected&&n(t);let r=e.push(n);t.setAttribute("vdelay",r-1)}AllENVs={};async parseRef(t,e,n,o,r,i=!1){e.setAttribute("vparsing","");let s=o,a=e.getAttribute("vrefof"),c=e.closest(`*[vref='${a}']`);c&&(o=c.$env),!r&&t&&(t.endsWith(".html")||(t+=".html"),r=await on.FetchUI(t,o,e.hasAttribute("root"))),o=Object.assign({},o,r?.env||{}),e.$env=o,e.$vsrc=t,o.$router=un.$router,o.$emit=(t,...n)=>{if(t=t.toLowerCase(),!e.$vevent)return;let o=e.$vevent[t];o&&"function"==typeof o&&o(...n)};let l=await this.setupRef(e,n,s,r,i);i?this.parseAttrs(e,l,o,r?.customAttrs):this.parseAttrs(e,n,s,r?.customAttrs);let u=this.parseVif(Array.from(e.childNodes),l,o);for(let f of u)this.parseDom(f,l,o);e.removeAttribute("vparsing"),this.mountRef(e,l,o,r)}async setupRef(t,e,n,r,i=!1){let s=y.Wrap({});if(r.setup){let e=r.setup.innerHTML;e=await y.ParseImport(e,s,t.$env,t.$vsrc),await y.AsyncRun(e,s,t.$env,{$node:t})}if(t.$refScope=e,t.$refData=s,i)return s;if(!t.$refSlots){let e=y.Wrap({});t.childNodes.forEach((t=>{let n=t.getAttribute?t.getAttribute("vslot"):"";n=n||"",e[n]||(e[n]=[]),e[n].push(t)})),t.$refSlots=e}t.innerHTML="";let a=r.body.cloneNode(!0);t.append(...a.childNodes),Object.keys(s).forEach((r=>{const i=hn.CamelToKebabCase(r);if("boolean"==typeof s[r]?(t.hasAttribute(r)||t.hasAttribute(i))&&(s[r]=!0):t.hasAttribute(r)?(s[r]=t.getAttribute(r),t.removeAttribute(r)):t.hasAttribute(i)&&(s[r]=t.getAttribute(i),t.removeAttribute(i)),t.hasAttribute(":"+r)||t.hasAttribute(":"+i)){let o=t.getAttribute(":"+r)||t.getAttribute(":"+i);t.removeAttribute(":"+r),t.removeAttribute(":"+i),delete s[r],o?y.Watch((()=>y.Run(o,e,n)),(()=>{s[r]=y.Run(o,e,n)}),{deep:!0}):y.Watch((()=>e[r]),(()=>{s[r]=e[r]}),{deep:!0})}if(t.hasAttribute("v:"+r)||t.hasAttribute("v:"+i)){let n=t.getAttribute("v:"+r)||t.getAttribute("v:"+i);t.removeAttribute("v:"+r),t.removeAttribute("v:"+i),n||(n=r),delete s[r],y.Watch((()=>o(n,e)),(t=>{t&&t.data&&t.key&&(s[r]=t.data[t.key])})),y.Watch((()=>s[r]),(()=>{let t=o(n,e);t&&t.data&&t.key&&(t.data[t.key]=s[r])}))}}));let c=Array.from(a.attributes);return c=c.filter((e=>!this.parseAttr(t,e.name,e.value,s,n)||(a.removeAttribute(e.name),!1))),c.forEach((e=>{if("class"===e.name)t.classList.add(...e.value.trim().split(/\s+/));else if("style"===e.name){let n=e.value.split(";");for(let e of n){let n=e.split(":");if(2===n.length&&!t.style[n[0]]){let e=n[0].trim();e.startsWith("--")?t.style.setProperty(e,n[1].trim()):t.style[e]=n[1].trim()}}}else t.getAttribute(e.name)||t.setAttribute(e.name,e.value)})),s}async mountRef(t,e,n,o){for(let r of o.scripts)r.hasAttribute("active")?this.onMountedRun(t,(()=>{y.AsyncRun(r.innerHTML,e,n,{$node:t,$watch:y.Watch})}),!1):y.AsyncRun(r.innerHTML,e,n,{$node:t,$watch:y.Watch})}parseAttrs(t,e,n,o){if("A"===t.nodeName&&this.parseAHref(t,e,n),Array.from(t.attributes).forEach((o=>{this.parseAttr(t,o.name,o.value,e,n)&&t.removeAttribute(o.name)})),o&&Object.keys(o).forEach((e=>{this.parseAttr(t,e,o[e],t.$refData,n)})),t.hasAttribute("v-show")){let o=t.getAttribute("v-show"),r=t.style.display;y.Watch((()=>{let i=y.Run(o,e,n);t.style.display=i?r:"none"}))}}parseAHref(t,e,n){if(!t.hasAttribute("href")&&!t.hasAttribute(":href"))return;y.Watch((()=>{let o=t.getAttribute("href");if(t.hasAttribute(":href")){let r=t.getAttribute(":href");t.removeAttribute(":href"),o=y.Run(r,e,n)}if(o&&!o.startsWith("#")&&!o.startsWith("http"))if(o.startsWith("@"))o=o.replaceAll("//","/"),t.setAttribute("href",o.slice(1));else if(o){let e=n?.root;e&&(o=e+o),t.setAttribute("href",o)}}));const o=e=>{let n=e?.fullPath;t.getAttribute("href")===n?t.setAttribute("active",""):t.removeAttribute("active")};o(un.$router.current),un.$router.onChange(o)}parseAttr(t,e,n,r,i){if(e.startsWith(":")){let o=e.slice(1);return"class"===o||"style"===o?this.handleStyle(t,o,n,r,i):y.Watch((()=>{let e;e=n?y.Run(n,r,i):r[o],hn.SetAttr(t,o,e)})),!0}if(e.startsWith("@"))return this.handleEvent(t,e,n,r,i),!0;if(e.indexOf("!")>-1);else if(e.startsWith("v:")){let e=o(n,r);if(e&&e.data&&e.key){let n=e.key,o=e.data;return hn.BindInputDomValue(t,o,n,y.Watch)}}else if("vdom"===e){let e=o(n,r);return e&&e.data&&e.key&&(e.data[e.key]=t),!0}return!1}handleStyle(t,e,n,o,r){let i="";y.Watch((()=>{let s=y.Run(n,o,r);if("function"==typeof s&&(s=s()),"class"===e){if(i&&(t.classList.remove(...i.split(/\s+/)),i=""),s instanceof Array)i="",s.forEach((t=>{if("string"==typeof t&&t.length)i+=" "+t;else if("object"==typeof t)for(let e in t)t[e]&&(i+=" "+e)}));else if("string"==typeof s&&s.length)i=s.trim();else if("object"==typeof s){i="";for(let t in s)s[t]&&(i+=" "+t)}i=i.trim(),i&&t.classList.add(...i.split(/\s+/))}else if("style"===e){if(i)if("object"==typeof i)for(let e in i)e.startsWith("--")?t.style.removeProperty(e):t.style[e]="";else if("string"==typeof i){let e=i.split(";");for(let n of e){let e=n.split(":");2===e.length&&(e[0].trim().startsWith("--")?t.style.removeProperty(e[0].trim()):t.style[e[0].trim()]="")}}if("object"==typeof s)for(let e in s)e.startsWith("--")?t.style.setProperty(e,s[e]):t.style[e]=s[e];else if("string"==typeof s){let e=s.split(";");for(let n of e){let e=n.split(":");2===e.length&&(e[0].trim().startsWith("--")?t.style.setProperty(e[0].trim(),e[1].trim()):t.style[e[0].trim()]=e[1].trim())}}i=s}}))}handleEvent(t,e,n,o,r){let i=e.slice(1).split("."),s={self:!1,prevent:!1,stop:!1},a=i[0];if("mounted"===a)this.onMountedRun(t,(t=>{let e=y.Run(n,o,r);"function"==typeof e&&e(t)}),!1);else if("outerclick"===a){let e=t=>{let e=y.Run(n,o,r,{$event:t});"function"==typeof e&&e(t)};hn.AddClicker(t,"outer",e)}else if(-1!==hn.EventsList.indexOf(a)){"keydown"!==a&&"keyup"!==a&&"keypress"!==a||"INPUT"!==t.tagName&&"TEXTAREA"!==t.tagName&&t.setAttribute("tabindex","0");let e=t=>{let e=y.Run(n,o,r,{$event:t});"function"==typeof e&&e(t)};i.slice(1).forEach((i=>{if(i.startsWith("delay")){let s=i.slice(5);s=s?s.endsWith("ms")?+s.slice(0,-2):s.endsWith("s")?1e3*+s.slice(0,-1):+s:1e3,isNaN(s)&&(s=1e3),e=e=>{let i=t["_"+a];i&&"number"==typeof i&&clearTimeout(i),t["_"+a]=setTimeout((()=>{let t=y.Run(n,o,r,{$event:e});"function"==typeof t&&t(e)}),s)}}s[i]=!0})),t.addEventListener(a,(t=>{(1>=i.length||"keydown"!==a&&"keyup"!=a&&"keypress"!=a||i[1]===t.key?.toLowerCase())&&(s.self&&t.currentTarget!==t.target||(s.prevent&&t.preventDefault(),s.stop&&t.stopPropagation(),e(t)))}))}else t.$vevent=t.$vevent||{},t.$vevent[a]=(...t)=>{let e=y.Run(n,o,r,{});"function"==typeof e&&e(...t)}}parseTextNode(t,e,n){let o,i=t.nodeValue.trim();if(!i)return;let s=0,a=-1,c=[];for(;null!==(o=r.exec(i));)if("{{"===o[0])a=o.index;else if("}}"===o[0]&&a>=0){s!==a&&c.push(i.slice(s,a)),c.push("");let r=i.slice(a+2,o.index),l=c.length;a=-1,s=o.index+2,y.Watch((()=>{c[l-1]=y.Run(r,e,n),"object"==typeof c[l-1]&&(c[l-1]=JSON.stringify(c[l-1])),t.nodeValue=c.join("")}))}c.push(i.slice(s)),t.nodeValue=c.join("")}vforDomCache={};parseVfor(t,e,n,o){e.removeAttribute("v-for");let r=i.exec(t);if(6===r?.length){let t=document.createElement("div");t.style.display="none";let i=y.GenUniqueID();this.vforDomCache[i]={},e.parentNode.replaceChild(t,e),y.Watch((()=>{let s=r[3]||r[2],a=r[4],c=y.Run(r[5],n,o),l=this.vforDomCache[i],u=new Set;if("function"==typeof c?c=c():"number"==typeof c&&(c=Array.from({length:c},((t,e)=>e))),null==c&&(c=[]),c.length,"object"==typeof c){let r=Object.keys(c),f=[];for(let t in r){let e=r[t],n="";n=c[e]&&c[e][y.DataID]?c[e][y.DataID]:e+"."+c[e],n=i+"."+n,u.add(n),f.push({k:e,vfk:n,val:c[e]})}for(let t of Object.keys(l))u.has(t)||(l[t]instanceof Array?l[t].forEach((t=>t.remove())):l[t].remove(),delete l[t]);let h=t;for(let i=f.length-1;i>=0;i--){let{k:r,vfk:c,val:u}=f[i],d=l[c];if(d){a&&(d.$vforData[a]="0"===r?0:+r||r),d.isConnected&&(d.nextSibling!==h&&t.parentNode.insertBefore(d,h),h=d);continue}let p=e.cloneNode(!0);l[c]=p;let m={[s]:u};a&&(m[a]="0"===r?0:+r||r),m=y.Wrap(m,n),p.$vforData=m,t.parentNode.insertBefore(p,h);let w=e.getAttribute("v-if");if(!w){this.parseDom(p,m,o),h=p;continue}p.removeAttribute("v-if");let b=-1;b=y.Watch((()=>{let e=l[c];if(e)if(y.Run(w,m,o)){if(e.vparsed||this.parseDom(e,m,o),!e.isConnected){let n=!1,o=t;for(let t in l)if(t!==c){if(n&&l[t].isConnected){o=l[t];break}}else n=!0;t.parentNode.insertBefore(e,o)}}else e.isConnected?e.remove():this.onMountedRun(e,(t=>{e.remove()}));else y.Cancel(b)})),p.isConnected&&(h=p)}}}))}}parseVif(t,e,n){let o={now:document.createElement("div"),conds:[],doms:[]};const r=t=>{let o={now:t.now,conds:t.conds,doms:t.doms},r=[];for(let e in o.conds){let t=o.conds[e];t=""===t?"true":"Boolean("+t+")",r.push(t)}let i=`let res = [${r.join(",")}]\n return res.indexOf(true)`;y.Watch((()=>{let t=y.Run(i,e,n),r=o.doms[t];return r||(r=document.createElement("div"),r.style.display="none"),r}),(t=>{t&&(this.onMountedRun(o.now,(e=>{e.replaceWith(t),o.now=t})),t?.vparsed||this.parseDom(t,e,n))}))};let i=t.filter((t=>!(t.getAttribute&&!t.getAttribute("v-for")&&(null!==t.getAttribute("v-if")?(o.conds.length>0&&(r(o),o={now:document.createElement("div"),conds:[],doms:[]}),t.replaceWith(o.now),o.conds.push(t.getAttribute("v-if")),t.removeAttribute("v-if"),o.doms.push(t),1):null!==t.getAttribute("v-else-if")?(o.conds.push(t.getAttribute("v-else-if")),t.removeAttribute("v-else-if"),o.doms.push(t),t.remove(),1):null!==t.getAttribute("v-else")&&(o.conds.push(""),t.removeAttribute("v-else"),o.doms.push(t),t.remove(),1)))));return o.conds.length>0&&r(o),i}parseSlots(t,e,n){let o=t.getAttribute("vrefof"),r=t.closest(`*[vref='${o}']`);if(!r)return void this.onMountedRun(t,(t=>{this.parseSlots(t,e,n)}));for(;;){let t=r?.parentNode.closest("*[vref]");if(!t)break;if(t.getAttribute("vref")!==o)break;r=t}let i=t.getAttribute("name")||"";if(t.getAttribute(":name")){let o=t.getAttribute(":name");t.removeAttribute(":name"),i=y.Run(o,e,n)}return t.originContent||(t.$originContent=Array.from(t.childNodes),t.innerHTML=""),t.$slotCache={},y.Watch((()=>{let o=r.$refSlots||{},s=r.$refScope||{},a=o[i];if(a&&a.length>0){let o=a[0].hashID;if(o){if(t.$slotCache[o])return t.innerHTML="",void t.append(...t.$slotCache[o])}else o=y.GenUniqueID(),a[0].hashID=o;t.innerHTML="",a=a.map((t=>t.cloneNode(!0))),t.append(...a);let r=s;if(null!==t.getAttribute("vbind")){let n=t.getAttribute("vbind").split(",").map((t=>t.trim()));r=y.Wrap({}),n.forEach((t=>{e.hasOwnProperty(t)&&(r[t]=e[t])})),y.SetDataRoot(r,s)}let i="";a.find((t=>!(!t.getAttribute||!t.getAttribute("vrefof")||(i=t.getAttribute("vrefof"),0))));let c=n;if(i){let e=t.closest(`*[vref='${i}']`);c=e?.$env||n}a=this.parseVif(a,r,c),a.forEach((t=>this.parseDom(t,r,c))),t.$slotCache[o]=a}else{t.innerHTML="",t.append(...t.$originContent);let o=!1;t.$originContent.forEach((t=>{t.hasAttribute&&t.vparsed&&(o=!0)})),o||(t.$originContent=this.parseVif(t.$originContent,e,n),t.$originContent.forEach((t=>this.parseDom(t,e,n))))}})),this.parseAttrs(t,e,n),t}}(document.body))}()},"function"==typeof define&&define.amd?define(t):t(); \ No newline at end of file +var t;t=function(){const t=[],e=[];function n(){return`${performance.now().toString(36)}-${Math.random().toString(36).substring(2,5)}`}function o(t,e=new Set){if(t&&"object"==typeof t&&!e.has(t)){e.add(t);for(let n in t)o(t[n],e)}return t}setInterval((()=>{let n=new Set(e.splice(0)),o=0;for(let e of n)t[e]&&(t[e](),o++);return o}),25),window.$vupdate=e=>{t[e]()};var r=[];const i=Symbol("isProxy"),s=Symbol("DataID"),a=Symbol("bind"),c=Symbol("root"),l=Symbol("root arg");function u(t,e){t[c]=e,Object.keys(e).forEach((e=>{e in t||(t[e]=l)}))}function f(t){return!(!t||"object"!=typeof t||t instanceof Node||t instanceof Date||t instanceof RegExp||t instanceof Event||t.t||t.constructor!==Object&&t.constructor!==Array)}function h(t,e){if(!t||!t[i]||!f(e))return e;let n=t[a];if(!e[i]){if(Array.isArray(e)&&Array.isArray(t)){t.length=0;for(let n=0;n{e.hasOwnProperty(n)||delete t[n]})),Object.keys(e).forEach((n=>{t[n]?.[i]?t[n]=h(t[n],e[n]):t[n]=e[n]})),t}if(e[s]===t[s])return e;for(let o in n)if(e[a][o]?.indexOf){const t=e[a][o],r=new Set(t);for(let e of n[o])r.has(e)||(t.push(e),r.add(e))}else e[a][o]=n[o];for(let o in e)o in t&&t[o]?.[i]&&(e[o]=h(t[o],e[o]));return e}let d=!1;const p={console,window,prompt:prompt.bind(window),alert:alert.bind(window),confirm:confirm.bind(window),RegExp,document,Array,Object,Math,Date,JSON,Symbol,Number,eval,isNaN,parseInt,parseFloat,setTimeout:setTimeout.bind(window),setInterval:setInterval.bind(window),clearTimeout:clearTimeout.bind(window),clearInterval:clearInterval.bind(window),encodeURIComponent,btoa:btoa.bind(window),fetch:fetch.bind(window),TextDecoder,history,requestAnimationFrame:requestAnimationFrame.bind(window)};function m(t,e,n){const o=new Proxy(t,{has:(t,e)=>!0,get(o,r,i){let s;return"$data"===r?s=t:"$env"===r?s=e:r in o?s=Reflect.get(o,r,i):r in e?s=e[r]:n&&r in n?s=n[r]:r in p?s=p[r]:r in window&&(s=window[r]),s},set:(t,e,n,o)=>Reflect.set(t,e,n,o)});return o}const w=Object.getPrototypeOf((async function(){})).constructor;function b(t,e){if(t.startsWith("/"))return t;const n=e.substring(0,e.lastIndexOf("/")).split("/").filter((t=>""!==t)),o=t.split("/").filter((t=>""!==t));for(const r of o)if(".."===r)n.length>0&&n.pop();else{if("."===r)continue;n.push(r)}return"/"+n.join("/")}const y={Wrap:function o(p,m=void 0){const w=n();let b=!1;"[object Array]"==={}.toString.call(p)&&(b=!0),m&&u(p,m);const y={},v={get(t,e,n){if(e===s)return w;if(e===i)return!0;if(e===a)return y;const u=Reflect.get(t,e,n);if(u===l)return t[c][e];if("symbol"==typeof e&&d)return u;if("function"==typeof u)return u;let h=-1;if(r.length>0){let t=e;h=r[r.length-1],b&&(t=""),y.hasOwnProperty(t)?-1==y[t].indexOf(h)&&y[t].push(h):y[t]=[h]}if(window.vdev,f(u)&&!u[i]){let r=o(u,void 0);return Reflect.set(t,e,r,n),r}return u},set(n,o,s,a){const u=Reflect.get(n,o,a);if(u===l)return n[c][o]=s,!0;if(u===s)return!0;if(d)return Reflect.set(n,o,s,a);let p=!0;if(Array.isArray(s)&&Array.isArray(u)){d=!0,u.length=0;for(let t=0;t{n(e())})):t.push(e);try{s=e(),i&&i.deep&&o(s)}catch(g){}finally{r.pop()}return"function"==typeof n&&n(s),a},Cancel:function(e){e>=0&&et.trim()))}const i=await import(t);"string"==typeof o?i.default?e[o]=i.default:e[o]=i:o.forEach((t=>{t in i?e[t]=i[t]:t in i.default&&(e[t]=i.default[t])}))}catch(l){}}return s.trim()}};class v{constructor(){this.events={}}on(t,e,n=null){if("function"!=typeof e)throw Error("\u56de\u8c03\u51fd\u6570\u5fc5\u987b\u662f\u4e00\u4e2a\u51fd\u6570");this.events[t]||(this.events[t]=[]);const o={callback:e,context:n};return this.events[t].push(o),()=>this.off(t,e,n)}once(t,e,n=null){const o=(...r)=>{this.off(t,o,n),e.apply(n,r)};return this.on(t,o,n)}off(t,e=null,n=null){this.events[t]&&(e?(this.events[t]=this.events[t].filter((t=>!(t.callback===e&&t.context===n))),0===this.events[t].length&&delete this.events[t]):delete this.events[t])}emit(t,...e){this.events[t]&&[...this.events[t]].forEach((t=>{try{t.callback.apply(t.context,e)}catch(n){}}))}listenerCount(t){return this.events[t]?this.events[t].length:0}eventNames(){return Object.keys(this.events)}removeAllListeners(){this.events={}}hasListeners(t){return this.listenerCount(t)>0}}function g(t,e){return function(){return t.apply(e,arguments)}}const{toString:x}=Object.prototype,{getPrototypeOf:R}=Object,{iterator:k,toStringTag:O}=Symbol,T=(E=Object.create(null),t=>{const e=x.call(t);return E[e]||(E[e]=e.slice(8,-1).toLowerCase())});var E;const S=t=>(t=t.toLowerCase(),e=>T(e)===t),A=t=>e=>typeof e===t,{isArray:j}=Array,$=A("undefined"),N=S("ArrayBuffer"),P=A("string"),C=A("function"),U=A("number"),F=t=>null!==t&&"object"==typeof t,D=t=>{if("object"!==T(t))return!1;const e=R(t);return!(null!==e&&e!==Object.prototype&&null!==Object.getPrototypeOf(e)||O in t||k in t)},L=S("Date"),I=S("File"),z=S("Blob"),M=S("FileList"),q=S("URLSearchParams"),[B,_,H,V]=["ReadableStream","Request","Response","Headers"].map(S);function X(t,e,{allOwnKeys:n=!1}={}){if(null==t)return;let o,r;if("object"!=typeof t&&(t=[t]),j(t))for(o=0,r=t.length;r>o;o++)e.call(null,t[o],o,t);else{const r=n?Object.getOwnPropertyNames(t):Object.keys(t),i=r.length;let s;for(o=0;i>o;o++)s=r[o],e.call(null,t[s],s,t)}}function J(t,e){e=e.toLowerCase();const n=Object.keys(t);let o,r=n.length;for(;r-- >0;)if(o=n[r],e===o.toLowerCase())return o;return null}const W="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:global,K=t=>!$(t)&&t!==W,G=(Z="undefined"!=typeof Uint8Array&&R(Uint8Array),t=>Z&&t instanceof Z);var Z;const Y=S("HTMLFormElement"),Q=(({hasOwnProperty:t})=>(e,n)=>t.call(e,n))(Object.prototype),tt=S("RegExp"),et=(t,e)=>{const n=Object.getOwnPropertyDescriptors(t),o={};X(n,((n,r)=>{let i;!1!==(i=e(n,r,t))&&(o[r]=i||n)})),Object.defineProperties(t,o)},nt=S("AsyncFunction"),ot=(rt="function"==typeof setImmediate,it=C(W.postMessage),rt?setImmediate:it?(st="axios@"+Math.random(),at=[],W.addEventListener("message",(({source:t,data:e})=>{t===W&&e===st&&at.length&&at.shift()()}),!1),t=>{at.push(t),W.postMessage(st,"*")}):t=>setTimeout(t));var rt,it,st,at;const ct="undefined"!=typeof queueMicrotask?queueMicrotask.bind(W):"undefined"!=typeof process&&process.nextTick||ot,lt={isArray:j,isArrayBuffer:N,isBuffer:function(t){return null!==t&&!$(t)&&null!==t.constructor&&!$(t.constructor)&&C(t.constructor.isBuffer)&&t.constructor.isBuffer(t)},isFormData:t=>{let e;return t&&("function"==typeof FormData&&t instanceof FormData||C(t.append)&&("formdata"===(e=T(t))||"object"===e&&C(t.toString)&&"[object FormData]"===t.toString()))},isArrayBufferView:function(t){let e;return e="undefined"!=typeof ArrayBuffer&&ArrayBuffer.isView?ArrayBuffer.isView(t):t&&t.buffer&&N(t.buffer),e},isString:P,isNumber:U,isBoolean:t=>!0===t||!1===t,isObject:F,isPlainObject:D,isReadableStream:B,isRequest:_,isResponse:H,isHeaders:V,isUndefined:$,isDate:L,isFile:I,isBlob:z,isRegExp:tt,isFunction:C,isStream:t=>F(t)&&C(t.pipe),isURLSearchParams:q,isTypedArray:G,isFileList:M,forEach:X,merge:function t(){const{caseless:e}=K(this)&&this||{},n={},o=(o,r)=>{const i=e&&J(n,r)||r;D(n[i])&&D(o)?n[i]=t(n[i],o):D(o)?n[i]=t({},o):j(o)?n[i]=o.slice():n[i]=o};for(let r=0,i=arguments.length;i>r;r++)arguments[r]&&X(arguments[r],o);return n},extend:(t,e,n,{allOwnKeys:o}={})=>(X(e,((e,o)=>{n&&C(e)?t[o]=g(e,n):t[o]=e}),{allOwnKeys:o}),t),trim:t=>t.trim?t.trim():t.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,""),stripBOM:t=>(65279===t.charCodeAt(0)&&(t=t.slice(1)),t),inherits:(t,e,n,o)=>{t.prototype=Object.create(e.prototype,o),t.prototype.constructor=t,Object.defineProperty(t,"super",{value:e.prototype}),n&&Object.assign(t.prototype,n)},toFlatObject:(t,e,n,o)=>{let r,i,s;const a={};if(e=e||{},null==t)return e;do{for(r=Object.getOwnPropertyNames(t),i=r.length;i-- >0;)s=r[i],o&&!o(s,t,e)||a[s]||(e[s]=t[s],a[s]=!0);t=!1!==n&&R(t)}while(t&&(!n||n(t,e))&&t!==Object.prototype);return e},kindOf:T,kindOfTest:S,endsWith:(t,e,n)=>{t+="",(void 0===n||n>t.length)&&(n=t.length),n-=e.length;const o=t.indexOf(e,n);return-1!==o&&o===n},toArray:t=>{if(!t)return null;if(j(t))return t;let e=t.length;if(!U(e))return null;const n=Array(e);for(;e-- >0;)n[e]=t[e];return n},forEachEntry:(t,e)=>{const n=(t&&t[k]).call(t);let o;for(;(o=n.next())&&!o.done;){const n=o.value;e.call(t,n[0],n[1])}},matchAll:(t,e)=>{let n;const o=[];for(;null!==(n=t.exec(e));)o.push(n);return o},isHTMLForm:Y,hasOwnProperty:Q,hasOwnProp:Q,reduceDescriptors:et,freezeMethods:t=>{et(t,((e,n)=>{if(C(t)&&-1!==["arguments","caller","callee"].indexOf(n))return!1;const o=t[n];C(o)&&(e.enumerable=!1,"writable"in e?e.writable=!1:e.set||(e.set=()=>{throw Error("Can not rewrite read-only method '"+n+"'")}))}))},toObjectSet:(t,e)=>{const n={},o=t=>{t.forEach((t=>{n[t]=!0}))};return j(t)?o(t):o((t+"").split(e)),n},toCamelCase:t=>t.toLowerCase().replace(/[-_\s]([a-z\d])(\w*)/g,(function(t,e,n){return e.toUpperCase()+n})),noop:()=>{},toFiniteNumber:(t,e)=>null!=t&&Number.isFinite(t=+t)?t:e,findKey:J,global:W,isContextDefined:K,isSpecCompliantForm:function(t){return!!(t&&C(t.append)&&"FormData"===t[O]&&t[k])},toJSONObject:t=>{const e=[,,,,,,,,,,],n=(t,o)=>{if(F(t)){if(e.indexOf(t)>=0)return;if(!("toJSON"in t)){e[o]=t;const r=j(t)?[]:{};return X(t,((t,e)=>{const i=n(t,o+1);!$(i)&&(r[e]=i)})),e[o]=void 0,r}}return t};return n(t,0)},isAsyncFn:nt,isThenable:t=>t&&(F(t)||C(t))&&C(t.then)&&C(t.catch),setImmediate:ot,asap:ct,isIterable:t=>null!=t&&C(t[k])};function ut(t,e,n,o,r){Error.call(this),Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):this.stack=Error().stack,this.message=t,this.name="AxiosError",e&&(this.code=e),n&&(this.config=n),o&&(this.request=o),r&&(this.response=r,this.status=r.status?r.status:null)}lt.inherits(ut,Error,{toJSON:function(){return{message:this.message,name:this.name,description:this.description,number:this.number,fileName:this.fileName,lineNumber:this.lineNumber,columnNumber:this.columnNumber,stack:this.stack,config:lt.toJSONObject(this.config),code:this.code,status:this.status}}});const ft=ut.prototype,ht={};function dt(t){return lt.isPlainObject(t)||lt.isArray(t)}function pt(t){return lt.endsWith(t,"[]")?t.slice(0,-2):t}function mt(t,e,n){return t?t.concat(e).map((function(t,e){return t=pt(t),!n&&e?"["+t+"]":t})).join(n?".":""):e}["ERR_BAD_OPTION_VALUE","ERR_BAD_OPTION","ECONNABORTED","ETIMEDOUT","ERR_NETWORK","ERR_FR_TOO_MANY_REDIRECTS","ERR_DEPRECATED","ERR_BAD_RESPONSE","ERR_BAD_REQUEST","ERR_CANCELED","ERR_NOT_SUPPORT","ERR_INVALID_URL"].forEach((t=>{ht[t]={value:t}})),Object.defineProperties(ut,ht),Object.defineProperty(ft,"isAxiosError",{value:!0}),ut.from=(t,e,n,o,r,i)=>{const s=Object.create(ft);return lt.toFlatObject(t,s,(function(t){return t!==Error.prototype}),(t=>"isAxiosError"!==t)),ut.call(s,t.message,e,n,o,r),s.cause=t,s.name=t.name,i&&Object.assign(s,i),s};const wt=lt.toFlatObject(lt,{},null,(function(t){return/^is[A-Z]/.test(t)}));function bt(t,e,n){if(!lt.isObject(t))throw new TypeError("target must be an object");e=e||new FormData;const o=(n=lt.toFlatObject(n,{metaTokens:!0,dots:!1,indexes:!1},!1,(function(t,e){return!lt.isUndefined(e[t])}))).metaTokens,r=n.visitor||l,i=n.dots,s=n.indexes,a=(n.Blob||"undefined"!=typeof Blob&&Blob)&<.isSpecCompliantForm(e);if(!lt.isFunction(r))throw new TypeError("visitor must be a function");function c(t){if(null===t)return"";if(lt.isDate(t))return t.toISOString();if(lt.isBoolean(t))return t.toString();if(!a&<.isBlob(t))throw new ut("Blob is not supported. Use a Buffer instead.");return lt.isArrayBuffer(t)||lt.isTypedArray(t)?a&&"function"==typeof Blob?new Blob([t]):Buffer.from(t):t}function l(t,n,r){let a=t;if(t&&!r&&"object"==typeof t)if(lt.endsWith(n,"{}"))n=o?n:n.slice(0,-2),t=JSON.stringify(t);else if(lt.isArray(t)&&function(t){return lt.isArray(t)&&!t.some(dt)}(t)||(lt.isFileList(t)||lt.endsWith(n,"[]"))&&(a=lt.toArray(t)))return n=pt(n),a.forEach((function(t,o){!lt.isUndefined(t)&&null!==t&&e.append(!0===s?mt([n],o,i):null===s?n:n+"[]",c(t))})),!1;return!!dt(t)||(e.append(mt(r,n,i),c(t)),!1)}const u=[],f=Object.assign(wt,{defaultVisitor:l,convertValue:c,isVisitable:dt});if(!lt.isObject(t))throw new TypeError("data must be an object");return function t(n,o){if(!lt.isUndefined(n)){if(-1!==u.indexOf(n))throw Error("Circular reference detected in "+o.join("."));u.push(n),lt.forEach(n,(function(n,i){!0===(!(lt.isUndefined(n)||null===n)&&r.call(e,n,lt.isString(i)?i.trim():i,o,f))&&t(n,o?o.concat(i):[i])})),u.pop()}}(t),e}function yt(t){const e={"!":"%21","'":"%27","(":"%28",")":"%29","~":"%7E","%20":"+","%00":"\0"};return encodeURIComponent(t).replace(/[!'()~]|%20|%00/g,(function(t){return e[t]}))}function vt(t,e){this.o=[],t&&bt(t,this,e)}const gt=vt.prototype;function xt(t){return encodeURIComponent(t).replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+").replace(/%5B/gi,"[").replace(/%5D/gi,"]")}function Rt(t,e,n){if(!e)return t;const o=n&&n.encode||xt;lt.isFunction(n)&&(n={serialize:n});const r=n&&n.serialize;let i;if(i=r?r(e,n):lt.isURLSearchParams(e)?e.toString():new vt(e,n).toString(o),i){const e=t.indexOf("#");-1!==e&&(t=t.slice(0,e)),t+=(-1===t.indexOf("?")?"?":"&")+i}return t}gt.append=function(t,e){this.o.push([t,e])},gt.toString=function(t){const e=t?function(e){return t.call(this,e,yt)}:yt;return this.o.map((function(t){return e(t[0])+"="+e(t[1])}),"").join("&")};const kt=class{constructor(){this.handlers=[]}use(t,e,n){return this.handlers.push({fulfilled:t,rejected:e,synchronous:!!n&&n.synchronous,runWhen:n?n.runWhen:null}),this.handlers.length-1}eject(t){this.handlers[t]&&(this.handlers[t]=null)}clear(){this.handlers&&(this.handlers=[])}forEach(t){lt.forEach(this.handlers,(function(e){null!==e&&t(e)}))}},Ot={silentJSONParsing:!0,forcedJSONParsing:!0,clarifyTimeoutError:!1},Tt={isBrowser:!0,classes:{URLSearchParams:"undefined"!=typeof URLSearchParams?URLSearchParams:vt,FormData:"undefined"!=typeof FormData?FormData:null,Blob:"undefined"!=typeof Blob?Blob:null},protocols:["http","https","file","blob","url","data"]},Et="undefined"!=typeof window&&"undefined"!=typeof document,St="object"==typeof navigator&&navigator||void 0,At=Et&&(!St||0>["ReactNative","NativeScript","NS"].indexOf(St.product)),jt="undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope&&"function"==typeof self.importScripts,$t=Et&&window.location.href||"http://localhost",Nt={...Object.freeze({__proto__:null,hasBrowserEnv:Et,hasStandardBrowserWebWorkerEnv:jt,hasStandardBrowserEnv:At,navigator:St,origin:$t}),...Tt};function Pt(t){function e(t,n,o,r){let i=t[r++];if("__proto__"===i)return!0;const s=Number.isFinite(+i),a=r>=t.length;return i=!i&<.isArray(o)?o.length:i,a?(lt.hasOwnProp(o,i)?o[i]=[o[i],n]:o[i]=n,!s):(o[i]&<.isObject(o[i])||(o[i]=[]),e(t,n,o[i],r)&<.isArray(o[i])&&(o[i]=function(t){const e={},n=Object.keys(t);let o;const r=n.length;let i;for(o=0;r>o;o++)i=n[o],e[i]=t[i];return e}(o[i])),!s)}if(lt.isFormData(t)&<.isFunction(t.entries)){const n={};return lt.forEachEntry(t,((t,o)=>{e(function(t){return lt.matchAll(/\w+|\[(\w*)]/g,t).map((t=>"[]"===t[0]?"":t[1]||t[0]))}(t),o,n,0)})),n}return null}const Ct={transitional:Ot,adapter:["xhr","http","fetch"],transformRequest:[function(t,e){const n=e.getContentType()||"",o=n.indexOf("application/json")>-1,r=lt.isObject(t);if(r&<.isHTMLForm(t)&&(t=new FormData(t)),lt.isFormData(t))return o?JSON.stringify(Pt(t)):t;if(lt.isArrayBuffer(t)||lt.isBuffer(t)||lt.isStream(t)||lt.isFile(t)||lt.isBlob(t)||lt.isReadableStream(t))return t;if(lt.isArrayBufferView(t))return t.buffer;if(lt.isURLSearchParams(t))return e.setContentType("application/x-www-form-urlencoded;charset=utf-8",!1),t.toString();let i;if(r){if(n.indexOf("application/x-www-form-urlencoded")>-1)return function(t,e){return bt(t,new Nt.classes.URLSearchParams,Object.assign({visitor:function(t,e,n,o){return Nt.isNode&<.isBuffer(t)?(this.append(e,t.toString("base64")),!1):o.defaultVisitor.apply(this,arguments)}},e))}(t,this.formSerializer).toString();if((i=lt.isFileList(t))||n.indexOf("multipart/form-data")>-1){const e=this.env&&this.env.FormData;return bt(i?{"files[]":t}:t,e&&new e,this.formSerializer)}}return r||o?(e.setContentType("application/json",!1),function(t){if(lt.isString(t))try{return(0,JSON.parse)(t),lt.trim(t)}catch(t){if("SyntaxError"!==t.name)throw t}return(0,JSON.stringify)(t)}(t)):t}],transformResponse:[function(t){const e=this.transitional||Ct.transitional,n=e&&e.forcedJSONParsing,o="json"===this.responseType;if(lt.isResponse(t)||lt.isReadableStream(t))return t;if(t&<.isString(t)&&(n&&!this.responseType||o)){const n=!(e&&e.silentJSONParsing)&&o;try{return JSON.parse(t)}catch(t){if(n){if("SyntaxError"===t.name)throw ut.from(t,ut.ERR_BAD_RESPONSE,this,null,this.response);throw t}}}return t}],timeout:0,xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",maxContentLength:-1,maxBodyLength:-1,env:{FormData:Nt.classes.FormData,Blob:Nt.classes.Blob},validateStatus:function(t){return t>=200&&300>t},headers:{common:{Accept:"application/json, text/plain, */*","Content-Type":void 0}}};lt.forEach(["delete","get","head","post","put","patch"],(t=>{Ct.headers[t]={}}));const Ut=Ct,Ft=lt.toObjectSet(["age","authorization","content-length","content-type","etag","expires","from","host","if-modified-since","if-unmodified-since","last-modified","location","max-forwards","proxy-authorization","referer","retry-after","user-agent"]),Dt=Symbol("internals");function Lt(t){return t&&(t+"").trim().toLowerCase()}function It(t){return!1===t||null==t?t:lt.isArray(t)?t.map(It):t+""}function zt(t,e,n,o,r){return lt.isFunction(o)?o.call(this,e,n):(r&&(e=n),lt.isString(e)?lt.isString(o)?-1!==e.indexOf(o):lt.isRegExp(o)?o.test(e):void 0:void 0)}class Mt{constructor(t){t&&this.set(t)}set(t,e,n){const o=this;function r(t,e,n){const r=Lt(e);if(!r)throw Error("header name must be a non-empty string");const i=lt.findKey(o,r);(!i||void 0===o[i]||!0===n||void 0===n&&!1!==o[i])&&(o[i||e]=It(t))}const i=(t,e)=>lt.forEach(t,((t,n)=>r(t,n,e)));if(lt.isPlainObject(t)||t instanceof this.constructor)i(t,e);else if(lt.isString(t)&&(t=t.trim())&&!/^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(t.trim()))i((t=>{const e={};let n,o,r;return t&&t.split("\n").forEach((function(t){r=t.indexOf(":"),n=t.substring(0,r).trim().toLowerCase(),o=t.substring(r+1).trim(),!n||e[n]&&Ft[n]||("set-cookie"===n?e[n]?e[n].push(o):e[n]=[o]:e[n]=e[n]?e[n]+", "+o:o)})),e})(t),e);else if(lt.isObject(t)&<.isIterable(t)){let n,o,r={};for(const e of t){if(!lt.isArray(e))throw TypeError("Object iterator must return a key-value pair");r[o=e[0]]=(n=r[o])?lt.isArray(n)?[...n,e[1]]:[n,e[1]]:e[1]}i(r,e)}else null!=t&&r(e,t,n);return this}get(t,e){if(t=Lt(t)){const n=lt.findKey(this,t);if(n){const t=this[n];if(!e)return t;if(!0===e)return function(t){const e=Object.create(null),n=/([^\s,;=]+)\s*(?:=\s*([^,;]+))?/g;let o;for(;o=n.exec(t);)e[o[1]]=o[2];return e}(t);if(lt.isFunction(e))return e.call(this,t,n);if(lt.isRegExp(e))return e.exec(t);throw new TypeError("parser must be boolean|regexp|function")}}}has(t,e){if(t=Lt(t)){const n=lt.findKey(this,t);return!(!n||void 0===this[n]||e&&!zt(0,this[n],n,e))}return!1}delete(t,e){const n=this;let o=!1;function r(t){if(t=Lt(t)){const r=lt.findKey(n,t);!r||e&&!zt(0,n[r],r,e)||(delete n[r],o=!0)}}return lt.isArray(t)?t.forEach(r):r(t),o}clear(t){const e=Object.keys(this);let n=e.length,o=!1;for(;n--;){const r=e[n];t&&!zt(0,this[r],r,t,!0)||(delete this[r],o=!0)}return o}normalize(t){const e=this,n={};return lt.forEach(this,((o,r)=>{const i=lt.findKey(n,r);if(i)return e[i]=It(o),void delete e[r];const s=t?function(t){return t.trim().toLowerCase().replace(/([a-z\d])(\w*)/g,((t,e,n)=>e.toUpperCase()+n))}(r):(r+"").trim();s!==r&&delete e[r],e[s]=It(o),n[s]=!0})),this}concat(...t){return this.constructor.concat(this,...t)}toJSON(t){const e=Object.create(null);return lt.forEach(this,((n,o)=>{null!=n&&!1!==n&&(e[o]=t&<.isArray(n)?n.join(", "):n)})),e}[Symbol.iterator](){return Object.entries(this.toJSON())[Symbol.iterator]()}toString(){return Object.entries(this.toJSON()).map((([t,e])=>t+": "+e)).join("\n")}getSetCookie(){return this.get("set-cookie")||[]}get[Symbol.toStringTag](){return"AxiosHeaders"}static from(t){return t instanceof this?t:new this(t)}static concat(t,...e){const n=new this(t);return e.forEach((t=>n.set(t))),n}static accessor(t){const e=(this[Dt]=this[Dt]={accessors:{}}).accessors,n=this.prototype;function o(t){const o=Lt(t);e[o]||(function(t,e){const n=lt.toCamelCase(" "+e);["get","set","has"].forEach((o=>{Object.defineProperty(t,o+n,{value:function(t,n,r){return this[o].call(this,e,t,n,r)},configurable:!0})}))}(n,t),e[o]=!0)}return lt.isArray(t)?t.forEach(o):o(t),this}}Mt.accessor(["Content-Type","Content-Length","Accept","Accept-Encoding","User-Agent","Authorization"]),lt.reduceDescriptors(Mt.prototype,(({value:t},e)=>{let n=e[0].toUpperCase()+e.slice(1);return{get:()=>t,set(t){this[n]=t}}})),lt.freezeMethods(Mt);const qt=Mt;function Bt(t,e){const n=this||Ut,o=e||n,r=qt.from(o.headers);let i=o.data;return lt.forEach(t,(function(t){i=t.call(n,i,r.normalize(),e?e.status:void 0)})),r.normalize(),i}function _t(t){return!(!t||!t.i)}function Ht(t,e,n){ut.call(this,t??"canceled",ut.ERR_CANCELED,e,n),this.name="CanceledError"}function Vt(t,e,n){const o=n.config.validateStatus;n.status&&o&&!o(n.status)?e(new ut("Request failed with status code "+n.status,[ut.ERR_BAD_REQUEST,ut.ERR_BAD_RESPONSE][Math.floor(n.status/100)-4],n.config,n.request,n)):t(n)}lt.inherits(Ht,ut,{i:!0});const Xt=(t,e,n=3)=>{let o=0;const r=function(t,e){const n=Array(t=t||10),o=Array(t);let r,i=0,s=0;return e=void 0!==e?e:1e3,function(a){const c=Date.now(),l=o[s];r||(r=c),n[i]=a,o[i]=c;let u=s,f=0;for(;u!==i;)f+=n[u++],u%=t;if(i=(i+1)%t,i===s&&(s=(s+1)%t),e>c-r)return;const h=l&&c-l;return h?Math.round(1e3*f/h):void 0}}(50,250);return function(t,e){let n,o,r=0,i=1e3/e;const s=(e,i=Date.now())=>{r=i,n=null,o&&(clearTimeout(o),o=null),t.apply(null,e)};return[(...t)=>{const e=Date.now(),a=e-r;i>a?(n=t,o||(o=setTimeout((()=>{o=null,s(n)}),i-a))):s(t,e)},()=>n&&s(n)]}((n=>{const i=n.loaded,s=n.lengthComputable?n.total:void 0,a=i-o,c=r(a);o=i,t({loaded:i,total:s,progress:s?i/s:void 0,bytes:a,rate:c||void 0,estimated:c&&s&&s>=i?(s-i)/c:void 0,event:n,lengthComputable:null!=s,[e?"download":"upload"]:!0})}),n)},Jt=(t,e)=>{const n=null!=t;return[o=>e[0]({lengthComputable:n,total:t,loaded:o}),e[1]]},Wt=t=>(...e)=>lt.asap((()=>t(...e))),Kt=Nt.hasStandardBrowserEnv?((t,e)=>n=>(n=new URL(n,Nt.origin),t.protocol===n.protocol&&t.host===n.host&&(e||t.port===n.port)))(new URL(Nt.origin),Nt.navigator&&/(msie|trident)/i.test(Nt.navigator.userAgent)):()=>!0,Gt=Nt.hasStandardBrowserEnv?{write(t,e,n,o,r,i){const s=[t+"="+encodeURIComponent(e)];lt.isNumber(n)&&s.push("expires="+new Date(n).toGMTString()),lt.isString(o)&&s.push("path="+o),lt.isString(r)&&s.push("domain="+r),!0===i&&s.push("secure"),document.cookie=s.join("; ")},read(t){const e=document.cookie.match(RegExp("(^|;\\s*)("+t+")=([^;]*)"));return e?decodeURIComponent(e[3]):null},remove(t){this.write(t,"",Date.now()-864e5)}}:{write(){},read:()=>null,remove(){}};function Zt(t,e,n){return!t||/^([a-z][a-z\d+\-.]*:)?\/\//i.test(e)&&0!=n?e:function(t,e){return e?t.replace(/\/?\/$/,"")+"/"+e.replace(/^\/+/,""):t}(t,e)}const Yt=t=>t instanceof qt?{...t}:t;function Qt(t,e){e=e||{};const n={};function o(t,e,n,o){return lt.isPlainObject(t)&<.isPlainObject(e)?lt.merge.call({caseless:o},t,e):lt.isPlainObject(e)?lt.merge({},e):lt.isArray(e)?e.slice():e}function r(t,e,n,r){return lt.isUndefined(e)?lt.isUndefined(t)?void 0:o(void 0,t,0,r):o(t,e,0,r)}function i(t,e){if(!lt.isUndefined(e))return o(void 0,e)}function s(t,e){return lt.isUndefined(e)?lt.isUndefined(t)?void 0:o(void 0,t):o(void 0,e)}function a(n,r,i){return i in e?o(n,r):i in t?o(void 0,n):void 0}const c={url:i,method:i,data:i,baseURL:s,transformRequest:s,transformResponse:s,paramsSerializer:s,timeout:s,timeoutMessage:s,withCredentials:s,withXSRFToken:s,adapter:s,responseType:s,xsrfCookieName:s,xsrfHeaderName:s,onUploadProgress:s,onDownloadProgress:s,decompress:s,maxContentLength:s,maxBodyLength:s,beforeRedirect:s,transport:s,httpAgent:s,httpsAgent:s,cancelToken:s,socketPath:s,responseEncoding:s,validateStatus:a,headers:(t,e,n)=>r(Yt(t),Yt(e),0,!0)};return lt.forEach(Object.keys(Object.assign({},t,e)),(function(o){const i=c[o]||r,s=i(t[o],e[o],o);lt.isUndefined(s)&&i!==a||(n[o]=s)})),n}const te=t=>{const e=Qt({},t);let n,{data:o,withXSRFToken:r,xsrfHeaderName:i,xsrfCookieName:s,headers:a,auth:c}=e;if(e.headers=a=qt.from(a),e.url=Rt(Zt(e.baseURL,e.url,e.allowAbsoluteUrls),t.params,t.paramsSerializer),c&&a.set("Authorization","Basic "+btoa((c.username||"")+":"+(c.password?unescape(encodeURIComponent(c.password)):""))),lt.isFormData(o))if(Nt.hasStandardBrowserEnv||Nt.hasStandardBrowserWebWorkerEnv)a.setContentType(void 0);else if(!1!==(n=a.getContentType())){const[t,...e]=n?n.split(";").map((t=>t.trim())).filter(Boolean):[];a.setContentType([t||"multipart/form-data",...e].join("; "))}if(Nt.hasStandardBrowserEnv&&(r&<.isFunction(r)&&(r=r(e)),r||!1!==r&&Kt(e.url))){const t=i&&s&&Gt.read(s);t&&a.set(i,t)}return e},ee="undefined"!=typeof XMLHttpRequest&&function(t){return new Promise((function(e,n){const o=te(t);let r=o.data;const i=qt.from(o.headers).normalize();let s,a,c,l,u,{responseType:f,onUploadProgress:h,onDownloadProgress:d}=o;function p(){l&&l(),u&&u(),o.cancelToken&&o.cancelToken.unsubscribe(s),o.signal&&o.signal.removeEventListener("abort",s)}let m=new XMLHttpRequest;function w(){if(!m)return;const o=qt.from("getAllResponseHeaders"in m&&m.getAllResponseHeaders());Vt((function(t){e(t),p()}),(function(t){n(t),p()}),{data:f&&"text"!==f&&"json"!==f?m.response:m.responseText,status:m.status,statusText:m.statusText,headers:o,config:t,request:m}),m=null}m.open(o.method.toUpperCase(),o.url,!0),m.timeout=o.timeout,"onloadend"in m?m.onloadend=w:m.onreadystatechange=function(){m&&4===m.readyState&&(0!==m.status||m.responseURL&&0===m.responseURL.indexOf("file:"))&&setTimeout(w)},m.onabort=function(){m&&(n(new ut("Request aborted",ut.ECONNABORTED,t,m)),m=null)},m.onerror=function(){n(new ut("Network Error",ut.ERR_NETWORK,t,m)),m=null},m.ontimeout=function(){let e=o.timeout?"timeout of "+o.timeout+"ms exceeded":"timeout exceeded";const r=o.transitional||Ot;o.timeoutErrorMessage&&(e=o.timeoutErrorMessage),n(new ut(e,r.clarifyTimeoutError?ut.ETIMEDOUT:ut.ECONNABORTED,t,m)),m=null},void 0===r&&i.setContentType(null),"setRequestHeader"in m&<.forEach(i.toJSON(),(function(t,e){m.setRequestHeader(e,t)})),lt.isUndefined(o.withCredentials)||(m.withCredentials=!!o.withCredentials),f&&"json"!==f&&(m.responseType=o.responseType),d&&([c,u]=Xt(d,!0),m.addEventListener("progress",c)),h&&m.upload&&([a,l]=Xt(h),m.upload.addEventListener("progress",a),m.upload.addEventListener("loadend",l)),(o.cancelToken||o.signal)&&(s=e=>{m&&(n(!e||e.type?new Ht(null,t,m):e),m.abort(),m=null)},o.cancelToken&&o.cancelToken.subscribe(s),o.signal&&(o.signal.aborted?s():o.signal.addEventListener("abort",s)));const b=function(t){const e=/^([-+\w]{1,25})(:?\/\/|:)/.exec(t);return e&&e[1]||""}(o.url);b&&-1===Nt.protocols.indexOf(b)?n(new ut("Unsupported protocol "+b+":",ut.ERR_BAD_REQUEST,t)):m.send(r||null)}))},ne=(t,e)=>{const{length:n}=t=t?t.filter(Boolean):[];if(e||n){let n,o=new AbortController;const r=function(t){if(!n){n=!0,s();const e=t instanceof Error?t:this.reason;o.abort(e instanceof ut?e:new Ht(e instanceof Error?e.message:e))}};let i=e&&setTimeout((()=>{i=null,r(new ut(`timeout ${e} of ms exceeded`,ut.ETIMEDOUT))}),e);const s=()=>{t&&(i&&clearTimeout(i),i=null,t.forEach((t=>{t.unsubscribe?t.unsubscribe(r):t.removeEventListener("abort",r)})),t=null)};t.forEach((t=>t.addEventListener("abort",r)));const{signal:a}=o;return a.unsubscribe=()=>lt.asap(s),a}},oe=function*(t,e){let n=t.byteLength;if(e>n)return void(yield t);let o,r=0;for(;n>r;)o=r+e,yield t.slice(r,o),r=o},re=(t,e,n,o)=>{const r=async function*(t,e){for await(const n of async function*(t){if(t[Symbol.asyncIterator])return void(yield*t);const e=t.getReader();try{for(;;){const{done:t,value:n}=await e.read();if(t)break;yield n}}finally{await e.cancel()}}(t))yield*oe(n,e)}(t,e);let i,s=0,a=t=>{i||(i=!0,o&&o(t))};return new ReadableStream({async pull(t){try{const{done:e,value:o}=await r.next();if(e)return a(),void t.close();let i=o.byteLength;if(n){let t=s+=i;n(t)}t.enqueue(new Uint8Array(o))}catch(t){throw a(t),t}},cancel:t=>(a(t),r.return())},{highWaterMark:2})},ie="function"==typeof fetch&&"function"==typeof Request&&"function"==typeof Response,se=ie&&"function"==typeof ReadableStream,ae=ie&&("function"==typeof TextEncoder?(ce=new TextEncoder,t=>ce.encode(t)):async t=>new Uint8Array(await new Response(t).arrayBuffer()));var ce;const le=(t,...e)=>{try{return!!t(...e)}catch(t){return!1}},ue=se&&le((()=>{let t=!1;const e=new Request(Nt.origin,{body:new ReadableStream,method:"POST",get duplex(){return t=!0,"half"}}).headers.has("Content-Type");return t&&!e})),fe=se&&le((()=>lt.isReadableStream(new Response("").body))),he={stream:fe&&(t=>t.body)};var de;ie&&(de=new Response,["text","arrayBuffer","blob","formData","stream"].forEach((t=>{!he[t]&&(he[t]=lt.isFunction(de[t])?e=>e[t]():(e,n)=>{throw new ut(`Response type '${t}' is not supported`,ut.ERR_NOT_SUPPORT,n)})})));const pe={http:null,xhr:ee,fetch:ie&&(async t=>{let{url:e,method:n,data:o,signal:r,cancelToken:i,timeout:s,onDownloadProgress:a,onUploadProgress:c,responseType:l,headers:u,withCredentials:f="same-origin",fetchOptions:h}=te(t);l=l?(l+"").toLowerCase():"text";let d,p=ne([r,i&&i.toAbortSignal()],s);const m=p&&p.unsubscribe&&(()=>{p.unsubscribe()});let w;try{if(c&&ue&&"get"!==n&&"head"!==n&&0!==(w=await(async(t,e)=>lt.toFiniteNumber(t.getContentLength())??(async t=>{if(null==t)return 0;if(lt.isBlob(t))return t.size;if(lt.isSpecCompliantForm(t)){const e=new Request(Nt.origin,{method:"POST",body:t});return(await e.arrayBuffer()).byteLength}return lt.isArrayBufferView(t)||lt.isArrayBuffer(t)?t.byteLength:(lt.isURLSearchParams(t)&&(t+=""),lt.isString(t)?(await ae(t)).byteLength:void 0)})(e))(u,o))){let t,n=new Request(e,{method:"POST",body:o,duplex:"half"});if(lt.isFormData(o)&&(t=n.headers.get("content-type"))&&u.setContentType(t),n.body){const[t,e]=Jt(w,Xt(Wt(c)));o=re(n.body,65536,t,e)}}lt.isString(f)||(f=f?"include":"omit");const r="credentials"in Request.prototype;d=new Request(e,{...h,signal:p,method:n.toUpperCase(),headers:u.normalize().toJSON(),body:o,duplex:"half",credentials:r?f:void 0});let i=await fetch(d,h);const s=fe&&("stream"===l||"response"===l);if(fe&&(a||s&&m)){const t={};["status","statusText","headers"].forEach((e=>{t[e]=i[e]}));const e=lt.toFiniteNumber(i.headers.get("content-length")),[n,o]=a&&Jt(e,Xt(Wt(a),!0))||[];i=new Response(re(i.body,65536,n,(()=>{o&&o(),m&&m()})),t)}l=l||"text";let b=await he[lt.findKey(he,l)||"text"](i,t);return!s&&m&&m(),await new Promise(((e,n)=>{Vt(e,n,{data:b,headers:qt.from(i.headers),status:i.status,statusText:i.statusText,config:t,request:d})}))}catch(e){if(m&&m(),e&&"TypeError"===e.name&&/Load failed|fetch/i.test(e.message))throw Object.assign(new ut("Network Error",ut.ERR_NETWORK,t,d),{cause:e.cause||e});throw ut.from(e,e&&e.code,t,d)}})};lt.forEach(pe,((t,e)=>{if(t){try{Object.defineProperty(t,"name",{value:e})}catch(t){}Object.defineProperty(t,"adapterName",{value:e})}}));const me=t=>"- "+t,we=t=>lt.isFunction(t)||null===t||!1===t,be=t=>{t=lt.isArray(t)?t:[t];const{length:e}=t;let n,o;const r={};for(let i=0;e>i;i++){let e;if(n=t[i],o=n,!we(n)&&(o=pe[(e=n+"").toLowerCase()],void 0===o))throw new ut(`Unknown adapter '${e}'`);if(o)break;r[e||"#"+i]=o}if(!o){const t=Object.entries(r).map((([t,e])=>`adapter ${t} `+(!1===e?"is not supported by the environment":"is not available in the build")));throw new ut("There is no suitable adapter to dispatch the request "+(e?t.length>1?"since :\n"+t.map(me).join("\n"):" "+me(t[0]):"as no adapter specified"),"ERR_NOT_SUPPORT")}return o};function ye(t){if(t.cancelToken&&t.cancelToken.throwIfRequested(),t.signal&&t.signal.aborted)throw new Ht(null,t)}function ve(t){return ye(t),t.headers=qt.from(t.headers),t.data=Bt.call(t,t.transformRequest),-1!==["post","put","patch"].indexOf(t.method)&&t.headers.setContentType("application/x-www-form-urlencoded",!1),be(t.adapter||Ut.adapter)(t).then((function(e){return ye(t),e.data=Bt.call(t,t.transformResponse,e),e.headers=qt.from(e.headers),e}),(function(e){return _t(e)||(ye(t),e&&e.response&&(e.response.data=Bt.call(t,t.transformResponse,e.response),e.response.headers=qt.from(e.response.headers))),Promise.reject(e)}))}const ge={};["object","boolean","number","function","string","symbol"].forEach(((t,e)=>{ge[t]=function(n){return typeof n===t||"a"+(1>e?"n ":" ")+t}}));const xe={};ge.transitional=function(t,e,n){function o(t,e){return"[Axios v1.10.0] Transitional option '"+t+"'"+e+(n?". "+n:"")}return(n,r,i)=>{if(!1===t)throw new ut(o(r," has been removed"+(e?" in "+e:"")),ut.ERR_DEPRECATED);return e&&!xe[r]&&(xe[r]=!0),!t||t(n,r,i)}},ge.spelling=function(t){return(t,e)=>!0};const Re={assertOptions:function(t,e,n){if("object"!=typeof t)throw new ut("options must be an object",ut.ERR_BAD_OPTION_VALUE);const o=Object.keys(t);let r=o.length;for(;r-- >0;){const i=o[r],s=e[i];if(s){const e=t[i],n=void 0===e||s(e,i,t);if(!0!==n)throw new ut("option "+i+" must be "+n,ut.ERR_BAD_OPTION_VALUE)}else if(!0!==n)throw new ut("Unknown option "+i,ut.ERR_BAD_OPTION)}},validators:ge},ke=Re.validators;class Oe{constructor(t){this.defaults=t||{},this.interceptors={request:new kt,response:new kt}}async request(t,e){try{return await this.l(t,e)}catch(t){if(t instanceof Error){let e={};Error.captureStackTrace?Error.captureStackTrace(e):e=Error();const n=e.stack?e.stack.replace(/^.+\n/,""):"";try{t.stack?n&&!(t.stack+"").endsWith(n.replace(/^.+\n.+\n/,""))&&(t.stack+="\n"+n):t.stack=n}catch(t){}}throw t}}l(t,e){"string"==typeof t?(e=e||{}).url=t:e=t||{},e=Qt(this.defaults,e);const{transitional:n,paramsSerializer:o,headers:r}=e;void 0!==n&&Re.assertOptions(n,{silentJSONParsing:ke.transitional(ke.boolean),forcedJSONParsing:ke.transitional(ke.boolean),clarifyTimeoutError:ke.transitional(ke.boolean)},!1),null!=o&&(lt.isFunction(o)?e.paramsSerializer={serialize:o}:Re.assertOptions(o,{encode:ke.function,serialize:ke.function},!0)),void 0!==e.allowAbsoluteUrls||(void 0!==this.defaults.allowAbsoluteUrls?e.allowAbsoluteUrls=this.defaults.allowAbsoluteUrls:e.allowAbsoluteUrls=!0),Re.assertOptions(e,{baseUrl:ke.spelling("baseURL"),withXsrfToken:ke.spelling("withXSRFToken")},!0),e.method=(e.method||this.defaults.method||"get").toLowerCase();let i=r&<.merge(r.common,r[e.method]);r&<.forEach(["delete","get","head","post","put","patch","common"],(t=>{delete r[t]})),e.headers=qt.concat(i,r);const s=[];let a=!0;this.interceptors.request.forEach((function(t){"function"==typeof t.runWhen&&!1===t.runWhen(e)||(a=a&&t.synchronous,s.unshift(t.fulfilled,t.rejected))}));const c=[];let l;this.interceptors.response.forEach((function(t){c.push(t.fulfilled,t.rejected)}));let u,f=0;if(!a){const t=[ve.bind(this),void 0];for(t.unshift.apply(t,s),t.push.apply(t,c),u=t.length,l=Promise.resolve(e);u>f;)l=l.then(t[f++],t[f++]);return l}u=s.length;let h=e;for(f=0;u>f;){const e=s[f++],n=s[f++];try{h=e(h)}catch(t){n.call(this,t);break}}try{l=ve(h)}catch(t){return Promise.reject(t)}for(f=0,u=c.length;u>f;)l=l.then(c[f++],c[f++]);return l}getUri(t){return Rt(Zt((t=Qt(this.defaults,t)).baseURL,t.url,t.allowAbsoluteUrls),t.params,t.paramsSerializer)}}lt.forEach(["delete","get","head","options"],(function(t){Oe.prototype[t]=function(e,n){return this.request(Qt(n||{},{method:t,url:e,data:(n||{}).data}))}})),lt.forEach(["post","put","patch"],(function(t){function e(e){return function(n,o,r){return this.request(Qt(r||{},{method:t,headers:e?{"Content-Type":"multipart/form-data"}:{},url:n,data:o}))}}Oe.prototype[t]=e(),Oe.prototype[t+"Form"]=e(!0)}));const Te=Oe;class Ee{constructor(t){if("function"!=typeof t)throw new TypeError("executor must be a function.");let e;this.promise=new Promise((function(t){e=t}));const n=this;this.promise.then((t=>{if(!n.u)return;let e=n.u.length;for(;e-- >0;)n.u[e](t);n.u=null})),this.promise.then=t=>{let e;const o=new Promise((t=>{n.subscribe(t),e=t})).then(t);return o.cancel=function(){n.unsubscribe(e)},o},t((function(t,o,r){n.reason||(n.reason=new Ht(t,o,r),e(n.reason))}))}throwIfRequested(){if(this.reason)throw this.reason}subscribe(t){this.reason?t(this.reason):this.u?this.u.push(t):this.u=[t]}unsubscribe(t){if(!this.u)return;const e=this.u.indexOf(t);-1!==e&&this.u.splice(e,1)}toAbortSignal(){const t=new AbortController,e=e=>{t.abort(e)};return this.subscribe(e),t.signal.unsubscribe=()=>this.unsubscribe(e),t.signal}static source(){let t;return{token:new Ee((function(e){t=e})),cancel:t}}}const Se=Ee,Ae={Continue:100,SwitchingProtocols:101,Processing:102,EarlyHints:103,Ok:200,Created:201,Accepted:202,NonAuthoritativeInformation:203,NoContent:204,ResetContent:205,PartialContent:206,MultiStatus:207,AlreadyReported:208,ImUsed:226,MultipleChoices:300,MovedPermanently:301,Found:302,SeeOther:303,NotModified:304,UseProxy:305,Unused:306,TemporaryRedirect:307,PermanentRedirect:308,BadRequest:400,Unauthorized:401,PaymentRequired:402,Forbidden:403,NotFound:404,MethodNotAllowed:405,NotAcceptable:406,ProxyAuthenticationRequired:407,RequestTimeout:408,Conflict:409,Gone:410,LengthRequired:411,PreconditionFailed:412,PayloadTooLarge:413,UriTooLong:414,UnsupportedMediaType:415,RangeNotSatisfiable:416,ExpectationFailed:417,ImATeapot:418,MisdirectedRequest:421,UnprocessableEntity:422,Locked:423,FailedDependency:424,TooEarly:425,UpgradeRequired:426,PreconditionRequired:428,TooManyRequests:429,RequestHeaderFieldsTooLarge:431,UnavailableForLegalReasons:451,InternalServerError:500,NotImplemented:501,BadGateway:502,ServiceUnavailable:503,GatewayTimeout:504,HttpVersionNotSupported:505,VariantAlsoNegotiates:506,InsufficientStorage:507,LoopDetected:508,NotExtended:510,NetworkAuthenticationRequired:511};Object.entries(Ae).forEach((([t,e])=>{Ae[e]=t}));const je=Ae,$e=function t(e){const n=new Te(e),o=g(Te.prototype.request,n);return lt.extend(o,Te.prototype,n,{allOwnKeys:!0}),lt.extend(o,n,null,{allOwnKeys:!0}),o.create=function(n){return t(Qt(e,n))},o}(Ut);$e.Axios=Te,$e.CanceledError=Ht,$e.CancelToken=Se,$e.isCancel=_t,$e.VERSION="1.10.0",$e.toFormData=bt,$e.AxiosError=ut,$e.Cancel=$e.CanceledError,$e.all=function(t){return Promise.all(t)},$e.spread=function(t){return function(e){return t.apply(null,e)}},$e.isAxiosError=function(t){return lt.isObject(t)&&!0===t.isAxiosError},$e.mergeConfig=Qt,$e.AxiosHeaders=qt,$e.formToJSON=t=>Pt(lt.isHTMLForm(t)?new FormData(t):t),$e.getAdapter=be,$e.HttpStatusCode=je,$e.default=$e;const Ne=$e,{Axios:Pe,AxiosError:Ce,CanceledError:Ue,isCancel:Fe,CancelToken:De,VERSION:Le,all:Ie,Cancel:ze,isAxiosError:Me,spread:qe,toFormData:Be,AxiosHeaders:_e,HttpStatusCode:He,formToJSON:Ve,getAdapter:Xe,mergeConfig:Je}=Ne,We=new class{constructor(){this.scopeAttribute="",this.scopeBody="",this.scopedKeyframes=new Map}parse(t,e){return this.scopeAttribute=`[vrefof="${e}"]`,this.scopeBody=`[vref="${e}"]`,this.scopedKeyframes.clear(),this.scopeSuffix=e.replace(/[^a-zA-Z0-9]/g,""),t=this.removeComments(t),this.collectKeyframes(t),this.parseRules(t)}collectKeyframes(t){const e=/@keyframes\s+([^\s{]+)/gi;let n;for(;null!==(n=e.exec(t));){const t=n[1],e=t+"-"+this.scopeSuffix;this.scopedKeyframes.set(t,e)}}removeComments(t){return t.replace(/\/\*[\s\S]*?\*\//g,"")}parseRules(t){let e="",n=0;for(;n=t.length)break;if("@"===t[n]){const o=this.parseAtRule(t,n);e+=o.content,n=o.endIndex}else{const o=this.parseNormalRule(t,n);e+=o.content,n=o.endIndex}}return e}parseAtRule(t,e){let n=e,o="";for(;n=t.length)return{content:o,endIndex:n};const r=o.toLowerCase().trim();if(r.startsWith("@keyframes"))return this.parseKeyframes(t,e);if(r.startsWith("@media"))return this.parseMedia(t,e);if(r.startsWith("@supports"))return this.parseSupports(t,e);{const e=this.findMatchingBrace(t,n);return{content:o+e.content,endIndex:e.endIndex}}}parseKeyframes(t,e){let n=e,o="";for(;n=t.length)return{content:o,endIndex:n};const r=this.findMatchingBrace(t,n),i=r.content,s=this.extractKeyframeName(o),a=this.scopedKeyframes.get(s);return a&&(o=o.replace(s,a)),o+=i,{content:o,endIndex:r.endIndex}}extractKeyframeName(t){const e=t.match(/@keyframes\s+([^\s{]+)/i);return e?e[1]:""}parseMedia(t,e){let n=e,o="";for(;n=t.length)return{content:o,endIndex:n};o+="{",n++;let r=1,i="";for(;n0;){if("{"===t[n])r++;else if("}"===t[n]&&(r--,0===r))break;i+=t[n],n++}return o+=this.parseRules(i),n=t.length)return{content:o,endIndex:n};const r=this.addScopeToSelector(o.trim()),i=this.findMatchingBrace(t,n);return{content:r+this.processRuleContent(i.content),endIndex:i.endIndex}}processRuleContent(t){let e=t;return e=e.replace(/animation\s*:\s*([^;]+);/gi,((t,e)=>`animation: ${this.processAnimationValue(e)};`)),e=e.replace(/animation-name\s*:\s*([^;]+);/gi,((t,e)=>`animation-name: ${this.processAnimationNames(e)};`)),e}processAnimationValue(t){return t.split(",").map((t=>t.trim())).map((t=>{const e=t.split(/\s+/);for(let n=0;n{const e=t.trim();return this.scopedKeyframes.get(e)||e})).join(", ")}addScopeToSelector(t){return t.trim()?t.split(",").map((t=>t.trim())).map((t=>this.addScopeToSingleSelector(t))).join(", "):t}addScopeToSingleSelector(t){if(!t.trim())return t;if(t.includes("::")){const e=t.split("::"),n=e[0],o="::"+e.slice(1).join("::");return this.addScopeToSelectorPart(n)+o}if(t.includes(":")&&!t.includes("::")){const e=t.match(/^([^:]+)(:.+)$/);if(e){const t=e[1],n=e[2];return this.addScopeToSelectorPart(t)+n}}return"*"===t||t.startsWith("@")?t:this.addScopeToSelectorPart(t)}addScopeToSelectorPart(t){const e=/(\s*[>+~]\s*|\s+)/;if(e.test(t)){const n=t.split(e);if(/^body(?:$|[:\[ ])/.test(n[0]))return n[0]=this.scopeBody+n[0].slice(4),n.join("");if(/^:root(?:$|[:\[ ])/.test(n[0]))return n[0]=this.scopeBody+n[0].slice(5),n.join("");for(let t=n.length-1;t>=0;t--)if(n[t].trim()&&!e.test(n[t])){let e=n[t].trim();n[t]=/^body(?:$|[:\[ ])/.test(e)?this.scopeBody+e.slice(4):/^:root(?:$:[$:\[ ])/.test(e)?this.scopeBody+e.slice(5):n[t].trim()+this.scopeAttribute;break}return n.join("")}let n=(t=t.trim()).trim();return/^body(?:$|[:\[ ])/.test(n)?this.scopeBody+n.slice(4):/^:root(?:$:[$:\[ ])/.test(n)?this.scopeBody+n.slice(5):n+this.scopeAttribute}findMatchingBrace(t,e){let n=e,o="",r=0;for(;n{this.removeMessage(s),i&&i()},s.appendChild(t)}return this.container.appendChild(s),setTimeout((()=>{s.classList.add("show")}),10),o>0&&setTimeout((()=>{this.removeMessage(s),i&&i()}),o),s}removeMessage(t){t&&t.parentNode&&(t.classList.remove("show"),setTimeout((()=>{t.parentNode&&t.parentNode.removeChild(t)}),300))}success(t,e={}){return this.createMessage("success",t,e)}warning(t,e={}){return this.createMessage("warning",t,e)}error(t,e={}){return this.createMessage("error",t,e)}info(t,e={}){return this.createMessage("info",t,e)}h(t,e={}){return new Promise(((n,o)=>{const{title:r="\u63d0\u793a",type:i="confirm",inputValue:s="",confirmText:a="\u786e\u5b9a",cancelText:c="\u53d6\u6d88",onConfirm:l=null,onCancel:u=()=>{n("")}}=e,f=document.createElement("div");f.className="prompt-overlay";const h=document.createElement("div");h.className="prompt-dialog";const d=document.createElement("div");d.className="prompt-header";const p=document.createElement("h3");p.className="prompt-title",p.textContent=r;const m=document.createElement("button");m.className="prompt-close",m.innerHTML="×",d.appendChild(p),d.appendChild(m);const w=document.createElement("div");w.className="prompt-body";const b=document.createElement("div");b.className="prompt-content",b.textContent=t,w.appendChild(b);let y=null;"input"===i&&(y=document.createElement("input"),y.className="prompt-input",y.type="text",y.value=s,w.appendChild(y));const v=document.createElement("div");v.className="prompt-footer";const g=document.createElement("button");g.className="prompt-btn prompt-btn-cancel",g.textContent=c;const x=document.createElement("button");x.className="prompt-btn prompt-btn-confirm",x.textContent=a,v.appendChild(g),v.appendChild(x),h.appendChild(d),h.appendChild(w),h.appendChild(v),f.appendChild(h),document.body.appendChild(f),setTimeout((()=>{f.classList.add("show")}),10),y&&setTimeout((()=>{y.focus()}),300);const R=(t=null)=>(f.classList.remove("show"),setTimeout((()=>{f.parentNode&&f.parentNode.removeChild(f)}),300),t);m.onclick=()=>{R(),u?u():o(Error("cancelled"))},g.onclick=()=>{R(),u?u():o(Error("cancelled"))},x.onclick=()=>{const t=!y||y.value;R(),n(t),l&&l(t)};const k=t=>{"Escape"===t.key&&(R(),u?u():o(Error("cancelled")),document.removeEventListener("keydown",k))};document.addEventListener("keydown",k),f.onclick=t=>{t.target===f&&(R(),u?u():o(Error("cancelled")))}}))}confirm(t,e={}){return this.h(t,{...e,type:"confirm"})}prompt(t,e,n={}){return this.h(t,{...n,type:"input",inputValue:e})}};var Ge={},Ze={};const Ye={};function Qe(t,e){Array.from(t.childNodes).forEach((t=>{1===t.nodeType&&(t.setAttribute("vrefof",e),Qe(t,e))}))}async function tn(t,e,n,o){void 0===n&&(n="#"+function(){let t=(new Date).getTime().toString(36);t.length>4&&(t=t.substring(t.length-4));let e="";for(let n=0;4>n;n++)e+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".charAt(Math.floor(52*Math.random()));return e+t.padStart(4,"0")}()),n.endsWith(".html")&&(n=n.slice(0,-5));let r=(new DOMParser).parseFromString(t,"text/html");if(r.body.hasAttribute("scoped")&&!o)throw Error("HTTP error! status: 404");let i={url:n,heads:[],body:document.createElement("div"),setup:void 0,scripts:[],styles:"",txt:t,env:e,tmp:r,customAttrs:{}};if(i.heads=Array.from(r.querySelector("head")?.children),n&&(r.querySelectorAll("style").forEach((t=>{null===t.getAttribute("unscoped")?i.styles+=We.parse(t.innerHTML,n):i.styles+=t.innerHTML})),i.styles)){const t=document.createElement("style");t.innerHTML=i.styles,t.setAttribute("vref",n),document.head.appendChild(t)}return i.body.append(...r.querySelector("body").childNodes),i.body.querySelectorAll("script").forEach((t=>{""!=t.innerHTML.trim()?(t.hasAttribute("setup")?i.setup=t:t.hasAttribute("no-vhtml")||i.scripts.push(t),t.remove()):t.remove()})),Array.from(r.body.attributes).forEach((t=>{/^[a-zA-Z]/.test(t.name)?i.body.setAttribute(t.name,t.value):i.customAttrs[t.name]=t.value})),i.body.setAttribute("vref",n),Qe(i.body,n),o||await async function(t,e){for(let n of t.heads){let o=n.nodeName.toLowerCase();"link"===o?nn(n,e):"script"===o?await en(n,e):"title"===o&&(t.title=n.innerText)}}(i,e),i}function en(t,e){let n=t.getAttribute("src"),o=t.getAttribute("key"),r=e?.scoped;if(r&&n.startsWith("/")&&(n=r+n),n.startsWith("@")&&(n=n.slice(1)),n&&document.querySelector(`script[src="${n}"]`))return;if(o&&document.querySelector(`script[key="${o}"]`))return;let i=document.createElement("script");return i.src=n,i.key=o,i.type=t.getAttribute("type")||"text/javascript",new Promise(((t,e)=>{i.onload=()=>{t(i)},i.onerror=()=>e(Error("Failed to load script "+n)),document.head.appendChild(i)}))}async function nn(t,e){let n=t.getAttribute("href"),o=t.getAttribute("key"),r=e?.scoped;r&&n.startsWith("/")&&(n=r+n),n.startsWith("@")&&(n=n.slice(1)),n&&document.querySelector(`link[href="${n}"]`)||o&&document.querySelector(`link[key="${o}"]`)||(t.setAttribute("href",n),document.head.append(t))}const on={FetchUI:async function(t,e,n){t&&"/"!==t||(t="/scoped.html"),t.startsWith("http")||t.startsWith("@")||t.startsWith("/")||(t="/"+t);let o=e?.scoped;if(o&&t.startsWith("/")&&(t=o+t),t.startsWith("@")&&(t=t.slice(1)),Ge[t])return Promise.resolve(Ge[t]);if(Ze[t])return Ze[t];let r={};const i=fetch(t+"?random="+Math.random()).then((async e=>{if(!e.ok)throw Error("HTTP error! status: "+e.status);for(const[t,i]of e.headers.entries())t.startsWith("vhtml-")&&(r[t.slice(5)]=i);let n=r.scoped||"";t.startsWith("http")&&(n=new URL(t).origin+n,r.scoped=n);let o=await async function(t,e){if(!Ye[t=t||""]){let n=t.startsWith("http")?t:window.location.origin+t;Ye[t]=Object.assign({},e,{scoped:t,$G:y.Wrap({}),$bus:new v,$axios:Ne.create({baseURL:n}),$message:Ke,$router:null,$emit:null}),t===$vhtml.scoped||null===$vhtml.scoped?Ye[t].$router=$vhtml.$router:Ye[t].$router={addRoutes:()=>{},beforeEnter:()=>{}};try{await(await import(n+"/env.js")).default(Ye[t])}catch(g){}}return Ye[t]}(n,r);return Object.assign(r,o),e.text()})).then((e=>tn(e,r,t,n))).then((e=>(Ge[t]=e,e))).catch((e=>{e.message;let n=document.createElement("div");n.style.cssText="\n backgound:#aaa;\n height:100%;\n width: 100%;\n display:grid;\n place-items: center;\n",n.innerHTML=`\n
\n
404
\n

${t}

\n
\n`;let o={heads:[],body:n,setup:"",scripts:[],styles:"",txt:"",tmp:"",env:r,err:e};return Ge[t]=o,o})).finally((()=>{delete Ze[t]}));return Ze[t]=i,i},FetchFile:async function(t){return fetch(t).then((t=>{if(!t.ok)throw Error("HTTP error! status: "+t.status);return t.text()}))},LoadScript:en,LoadLink:nn,ParseUI:tn};function rn(t,e){let n,o;if(t.startsWith("http://")||t.startsWith("https://")){if(n=new URL(t),n.origin!==window.location.origin)return null;n.pathname.startsWith(e)&&(o=n.pathname.slice(e.length))}else n=new URL(t,window.location.href),o=n.pathname;const r={};return n.searchParams.forEach(((t,e)=>{r[e]=t})),{path:o,query:r,hash:n.hash}}class sn{constructor(t,e){this.originalPath=t,this.name=e,this.keys=[],this.regexp=this.pathToRegexp(t)}pathToRegexp(t){let e=t.replace(/:([^(/]+)/g,((t,e)=>(this.keys.push(e),`(?<${e}>[^/]+)`)));return e=e.replace(/\*(\w+)/g,((t,e)=>(this.keys.push(e),`(?<${e}>.*)`))),e=e.replace(/\*/g,".*"),RegExp(`^${e}$`)}match(t){let e;if("string"==typeof t)e=t;else{if(!t||"object"!=typeof t)return null;if(!t.path)return t.name&&t.name===this.name?{path:this.originalPath,params:t.params||{},matched:this.originalPath}:null;e=t.path}const n=this.regexp.exec(e);if(!n)return null;const o={};return this.keys.forEach((t=>{n.groups?.[t]&&(o[t]=n.groups[t])})),{path:this.originalPath,params:o,matched:n[0]}}}const an=new Map;class cn{constructor(t,e,n){this.vhtml=t,this.node=e,this.layoutDom=void 0,this.matchedRoute=n,this.htmlPath=this.resolveHtmlPath(n)}resolveHtmlPath(t){let e=t.route.component||t.route.path;return"function"==typeof e&&(e=e(t.path)),Object.entries(t.params).forEach((([t,n])=>{e=e.replace(":"+t,n)})),e.startsWith("/")||(e="/"+e),e.endsWith("/")&&(e=e.slice(0,-1)),e.endsWith(".html")||(e+=".html"),e}async mount(t,e,n){const o=await on.FetchUI(this.htmlPath,t);if(o.err){let n=document.createElement("div");return Object.assign(n.style,{width:"100%",height:"100%"}),n.append(...e),this.node.innerHTML="",this.node.append(n),void this.vhtml.parseRef(this.htmlPath,n,{},t,null,!0)}this.title=o.title||"";const r={},i=document.createElement("div");if(i.setAttribute("vsrc",this.htmlPath),r[""]=[i],this.slots=r,!n)return this.node.innerHTML="",this.node.append(i),void this.vhtml.parseRef(this.htmlPath,i,{},t,null);let s=an.get(n);if(s)this.layoutDom=s,this.activate();else{let e=n;e.startsWith("/")||(e="/"+n),e.endsWith(".html")||(e+=".html"),e.startsWith("/layout")||(e="/layout"+e);const o=await on.FetchUI(e,t);if(o.err)return this.node.innerHTML="",this.node.append(i),void this.vhtml.parseRef(this.htmlPath,i,{},t,null);s=o.body.cloneNode(!0),an.set(n,s),i.$refData=y.Wrap({}),s.$refSlots=y.Wrap({...r}),this.node.innerHTML="",this.node.append(s),this.layoutDom=s,this.vhtml.parseRef("/layout/"+n,s,{},t,null,!0)}}activate(){this.title&&(document.title=this.title);const t=this.layoutDom;if(t)t.querySelectorAll("vslot").forEach((e=>{e.closest("[vref]")===t&&this.slots[e.getAttribute("name")||""]&&(e.innerHTML="")})),Object.keys(t.$refSlots).forEach((e=>{delete t.$refSlots[e]})),Object.assign(t.$refSlots,this.slots),t.isConnected||(this.node.innerHTML=""),this.node.append(t);else{this.node.innerHTML="";const t=this.slots[""];t instanceof Array?this.node.append(...t):this.node.append(t)}}}const ln=new class{#t=[];#e=[];#n=null;#o="";#r=[];#i=new Map;#s=null;#a=null;#c=[];#l=!1;#u=null;#f=new Map;constructor(){this.init()}get routes(){return this.#t.slice()}get history(){return this.#e.slice()}get current(){return this.#n}get query(){return this.#n?.query||{}}get params(){return this.#n?.params||{}}get scoped(){return this.#o}onChange(t){this.#r.push(t)}addRoute(t){if(!t.path)throw Error("Route must have a path");"/"!=t.path&&t.path.endsWith("/")&&(t.path=t.path.slice(0,-1));const e={path:t.path,component:t.component,name:t.name,meta:t.meta||{},children:t.children||[],matcher:new sn(t.path,t.name),description:t.description||"",layout:t.layout||""};this.#t.push(e),t.name&&this.#f.set(t.name,e),t.children?.length>0&&t.children.forEach((n=>{const o=t.path+(n.path.startsWith("/")?n.path:"/"+n.path),r=n.layout||t.layout||"",i={...t.meta,...n.meta};this.addRoute({...n,path:o,parent:e,layout:r,meta:i})}))}addRoutes(t){t.forEach((t=>this.addRoute(t)))}#h(t,e){this.#r.forEach((n=>{if("function"==typeof n)try{n(t,e)}catch(o){}}))}#d(t){const e=this.#n;this.#n={path:t.path,fullPath:t.fullPath,params:t.params||{},query:t.query||{},hash:new URL(t.fullPath,window.location.origin).hash,meta:t.route?.meta||{},description:t.route?.description||"",layout:t.route?.layout||"",name:t.route?.name,matched:t.route?[t.route]:[]},this.#e.push(this.#n),this.#o&&!t.fullPath.startsWith("http")?history.pushState({},"",this.#o+t.fullPath):history.pushState({},"",t.fullPath),this.#h(this.#n,e)}matchRoute(t){const e=this.normalizeRouteTarget(t);if(!e)return null;const{path:n,query:o,params:r,name:i}=e;if(i){const t=this.#f.get(i);if(!t)return null;let e=t.path;Object.entries(r).forEach((([t,n])=>{e=e.replace(":"+t,n)}));const n=t.matcher.match(e);return n?{route:t,params:{...n.params,...r},matched:n.matched,path:e,query:o,name:i}:null}for(const s of this.#t){const t=s.matcher.match(n);if(t&&s.component)return{route:s,params:{...t.params,...r},matched:t.matched,description:s.description,layout:s.layout,path:n,query:o,name:s.name}}return null}normalizeRouteTarget(t){let e,n,o={},r={},i="";if("string"==typeof t){const n=rn(t,this.#o);if(!n)return null;e=n.path,o={...n.query},i=n.hash}else{if(!t||"object"!=typeof t)return null;if(t.path){const n=rn(t.path,this.#o);if(!n)return null;e=n.path,o={...n.query,...t.query||{}},i=t.hash||n.hash,r=t.params||{}}else{if(!t.name)return null;n=t.name,o=t.query||{},r=t.params||{},i=t.hash||""}}return e&&!e.startsWith("/")&&(e="/"+e),this.#o&&(e=e.startsWith(this.#o)?e.slice(this.#o.length):e),e.startsWith("/")||(e="/"+e),"/"!=e&&e.endsWith("/")&&(e=e.slice(0,-1)),{path:e,query:o,params:r,hash:i,name:n}}matchTo(t){const e=this.matchRoute(t);if(!e)return null;const{route:n,params:o,query:r,path:i,name:s}=e;let a="";r&&Object.keys(r).length>0&&(a="?"+Object.entries(r).map((([t,e])=>`${encodeURIComponent(t)}=${encodeURIComponent(e)}`)).join("&"));const c=(i||e.path)+a;return{route:n,params:o,query:r,name:s||n.name,path:i||e.path,fullPath:c,matched:[n]}}buildUrl(t,e={}){const n=new URL(t,window.location.origin);return Object.entries(e).forEach((([t,e])=>{n.searchParams.append(t,e)})),n}resolveRoutePath(t,e={}){let n=t.component||t.path;return Object.entries(e).forEach((([t,e])=>{n=n.replace(":"+t,e)})),"/"!==n&&""!==n||(n="/index"),n.startsWith("/")||(n="/"+n),n.endsWith(".html")&&(n=n.slice(0,-5)),n.endsWith("/")&&(n=n.slice(0,-1)),n}async#p(t){if(!t)return;const{route:e,params:n,query:o}=t,r={path:t.path,fullPath:t.fullPath,params:n,query:o,hash:new URL(t.fullPath,window.location.origin).hash,meta:e.meta,description:e.description,layout:e.layout,name:e.name,matched:[e]};if(this.beforeEnter)try{let t=!0;if(!1===await this.beforeEnter(r,this.#n,(e=>{e&&(t=!1,this.push(e))}))||!t)return}catch(a){return}const i=t.fullPath;let s=this.#i.get(i);this.#d(t),s?s.activate():(s=new cn(this.#u,this.#s,t),await s.mount(this.#a,this.#c,r.layout),this.#i.set(i,s))}async push(t){const e=this.matchTo(t);e?await this.#p(e):"string"==typeof t||t.path||t.name}replace(t){this.push(t),this.#e.length>1&&this.#e.splice(-2,1)}go(t){history.go(t)}back(){history.back()}forward(){history.forward()}init(){this.#l||(this.#l=!0,document.body.addEventListener("click",(t=>{const e=t.target.closest("a");if(!e)return;const n=e.getAttribute("href");!n||n.startsWith("http")||n.startsWith("#")||(t.preventDefault(),e.hasAttribute("reload")?window.location.href=n:this.push(n))}),!0),window.addEventListener("popstate",(()=>{this.push(window.location.href)})))}ParseVrouter(t,e,n){this.#s=e,this.#a=n,this.#o=n.scoped||"",this.#c=Array.from(e.childNodes),this.#u=t,this.push(window.location.href)}},un={$router:ln},fn=[];document.addEventListener("click",(t=>{fn.forEach((e=>{e?.dom instanceof Element&&"function"==typeof e?.callback&&(e.dom.contains(t.target)||e.callback(t))}))}));const hn={CamelToKebabCase:function(t){return 0===t.length?"":t.charAt(0).toLowerCase()+t.slice(1).replace(/([A-Z])/g,(function(t,e){return"-"+e.toLowerCase()}))},EventsList:["load","unload","beforeunload","resize","scroll","submit","reset","input","change","focus","blur","keydown","keypress","keyup","click","dblclick","contextmenu","mousedown","mouseup","mousemove","mouseover","mouseout","mouseenter","mouseleave","touchstart","touchmove","touchend","touchcancel","drag","dragstart","dragend","dragover","dragenter","dragleave","drop","copy","cut","paste","animationstart","animationend","animationiteration","transitionend","abort","error","loadstart","progress","play","pause","ended","volumechange","timeupdate","loadeddata","waiting","playing","online","offline","storage","visibilitychange"],BindInputDomValue:function(t,e,n,o){const r="string"==typeof t?document.querySelector(t):t;if(r){switch(r.type||r.tagName.toLowerCase()){case"text":case"password":case"email":case"tel":case"url":case"search":case"number":case"range":case"color":case"date":case"time":case"datetime-local":case"month":case"week":case"hidden":case"textarea":o((()=>e[n]),(t=>{r.value=void 0===t?"":t})),r.addEventListener("input",(function(){e[n]=this.value}));break;case"checkbox":o((function(){r.checked=!!e[n]})),r.addEventListener("change",(function(){e[n]=this.checked}));break;case"radio":o((()=>{r.checked=r.value===e[n]})),r.addEventListener("change",(function(){this.checked&&(e[n]=this.value)}));break;case"select-one":case"select-multiple":o((()=>{let t=e[n];if(r.multiple){const e=Array.isArray(t)?t:[];for(let t=0;t{if("outer"===e){let e=fn.length;return fn.push({dom:t,callback:n}),()=>{fn[e]=null}}}},dn=async t=>navigator.clipboard&&navigator.clipboard.writeText?navigator.clipboard.writeText(t):(prompt("http\u73af\u5883\u65e0\u6cd5\u81ea\u52a8\u590d\u5236\uff0c\u8bf7\u624b\u52a8\u590d\u5236\u5185\u5bb9\u5230\u526a\u8d34\u677f:",t),new Promise((t=>{})));class pn{postMessage=(t,e)=>{};constructor(t={}){this.options={highlightColor:"#007bff",overlayColor:"rgba(0, 123, 255, 0.1)",borderWidth:"2px",zIndex:1e4,showTagName:!0,...t},this.isActive=!1,this.selectedElement=null,this.currentHoverElement=null,this.overlay=null,this.selectedOverlay=null,this.tooltip=null,this.selectedTooltip=null,this.actionPanel=null,this.originalCursor="",this.init()}init(){this.createStyles(),this.bindEvents()}createStyles(){const t=document.createElement("style");t.textContent=`\n .div-selector-overlay {\n position: fixed;\n pointer-events: none;\n border: ${this.options.borderWidth} solid ${this.options.highlightColor};\n background: ${this.options.overlayColor};\n z-index: ${this.options.zIndex};\n transition: all 0.2s ease;\n box-sizing: border-box;\n }\n \n .div-selector-selected {\n position: fixed;\n pointer-events: none;\n border: ${this.options.borderWidth} solid #28a745;\n background: rgba(40, 167, 69, 0.1);\n z-index: ${this.options.zIndex-1};\n box-sizing: border-box;\n }\n \n .div-selector-tooltip {\n position: fixed;\n background: rgba(51, 51, 51, 0.95);\n cursor:pointer;\n color: white;\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-family: 'Consolas', 'Monaco', 'Courier New', monospace;\n z-index: ${this.options.zIndex+1};\n user-select: none;\n box-shadow: 0 2px 8px rgba(0,0,0,0.3);\n border: 1px solid rgba(255,255,255,0.1);\n backdrop-filter: blur(4px);\n }\n \n .div-selector-tooltip.hover {\n background: rgba(0, 123, 255, 0.9);\n }\n \n .div-selector-tooltip.selected {\n background: rgba(40, 167, 69, 0.9);\n border-color: rgba(40, 167, 69, 0.3);\n }\n \n .div-selector-actions {\n position: fixed;\n background: white;\n border: 1px solid #ddd;\n border-radius: 8px;\n padding: 8px;\n z-index: ${this.options.zIndex+2};\n box-shadow: 0 4px 16px rgba(0,0,0,0.15);\n display: flex;\n gap: 6px;\n min-width: 30px;\n backdrop-filter: blur(8px);\n }\n \n .div-selector-btn {\n padding: 4px 6px;\n border: 1px solid #ddd;\n background: white;\n border-radius: 6px;\n cursor: pointer;\n font-size: 12px;\n transition: all 0.2s ease;\n text-align: left;\n white-space: nowrap;\n }\n \n .div-selector-btn:hover {\n background: #f8f9fa;\n transform: translateX(2px);\n }\n \n .div-selector-btn.danger {\n color: #dc3545;\n border-color: #dc3545;\n }\n \n .div-selector-btn.danger:hover {\n background: #dc3545;\n color: white;\n }\n \n .div-selector-btn.primary {\n background: #007bff;\n color: white;\n border-color: #007bff;\n }\n \n .div-selector-btn.primary:hover {\n background: #0056b3;\n }\n \n .div-selector-active {\n cursor: crosshair !important;\n }\n `,document.head.appendChild(t)}bindEvents(){this.handleMouseMove=this.handleMouseMove.bind(this),this.handleClick=this.handleClick.bind(this),this.handleScroll=this.handleScroll.bind(this),this.handleResize=this.handleResize.bind(this)}activate(){this.isActive||(this.isActive=!0,this.originalCursor=document.body.style.cursor,document.body.classList.add("div-selector-active"),document.addEventListener("mousemove",this.handleMouseMove),document.addEventListener("click",this.handleClick),window.addEventListener("scroll",this.handleScroll),window.addEventListener("resize",this.handleResize),this.createOverlay(),this.createTooltip())}deactivate(){this.isActive&&(this.isActive=!1,document.body.style.cursor=this.originalCursor,document.body.classList.remove("div-selector-active"),document.removeEventListener("mousemove",this.handleMouseMove),document.removeEventListener("click",this.handleClick),window.removeEventListener("scroll",this.handleScroll),window.removeEventListener("resize",this.handleResize),this.removeOverlay(),this.removeTooltip())}handleMouseMove(t){if(!this.isActive)return;const e=document.elementFromPoint(t.clientX,t.clientY);if(!e)return;if(this.isPluginElement(e))return;const n="DIV"===e.tagName?e:e.closest("div,[vref]");n&&!this.isPluginElement(n)&&this.selectedElement!==n&&(this.currentHoverElement=n,this.highlightElement(n),this.updateHoverTooltip(n))}handleClick(t){if(!this.isActive)return;const e=document.elementFromPoint(t.clientX,t.clientY);if(!e)return;if(this.isPluginElement(e))return;t.preventDefault(),t.stopPropagation();const n="DIV"===e.tagName?e:e.closest("div");n&&!this.isPluginElement(n)&&(this.selectElement(n),this.deactivate())}handleScroll(){this.selectedElement&&(this.updateSelectedOverlay(),this.updateSelectedTooltip(),this.updateActionPanelPosition()),this.currentHoverElement&&!this.selectedElement&&(this.highlightElement(this.currentHoverElement),this.updateHoverTooltip(this.currentHoverElement))}handleResize(){this.selectedElement&&(this.updateSelectedOverlay(),this.updateSelectedTooltip(),this.updateActionPanelPosition())}isPluginElement(t){return t.closest(".div-selector-overlay, .div-selector-selected, .div-selector-tooltip, .div-selector-actions")}createOverlay(){this.overlay=document.createElement("div"),this.overlay.className="div-selector-overlay",this.overlay.style.display="none",document.body.appendChild(this.overlay)}createSelectedOverlay(){this.selectedOverlay=document.createElement("div"),this.selectedOverlay.className="div-selector-selected",document.body.appendChild(this.selectedOverlay)}createTooltip(){this.tooltip=document.createElement("div"),this.tooltip.className="div-selector-tooltip hover",this.tooltip.style.display="none",document.body.appendChild(this.tooltip)}createSelectedTooltip(){this.selectedTooltip=document.createElement("div"),this.selectedTooltip.className="div-selector-tooltip selected",document.body.appendChild(this.selectedTooltip)}highlightElement(t){if(!this.overlay)return;const e=t.getBoundingClientRect();this.overlay.style.display="block",this.overlay.style.left=e.left+"px",this.overlay.style.top=e.top+"px",this.overlay.style.width=e.width+"px",this.overlay.style.height=e.height+"px"}updateHoverTooltip(t){if(!this.tooltip)return;const e=this.getElementInfo(t),n=t.getBoundingClientRect();this.tooltip.textContent=e,this.tooltip.style.display="block";let o=n.left-8,r=n.top-this.tooltip.offsetHeight-8;0>o&&(o=8),0>r&&(r=n.top+8),this.tooltip.style.left=o+"px",this.tooltip.style.top=r+"px"}selectElement(t){this.clearSelection(),this.selectedElement=t,this.createSelectedOverlay(),this.createSelectedTooltip(),this.updateSelectedOverlay(),this.updateSelectedTooltip(),this.overlay&&(this.overlay.style.display="none"),this.tooltip&&(this.tooltip.style.display="none"),this.showActionPanel()}updateSelectedOverlay(){if(!this.selectedOverlay||!this.selectedElement)return;const t=this.selectedElement.getBoundingClientRect();this.selectedOverlay.style.left=t.left+"px",this.selectedOverlay.style.top=t.top+"px",this.selectedOverlay.style.width=t.width+"px",this.selectedOverlay.style.height=t.height+"px"}updateSelectedTooltip(){if(!this.selectedTooltip||!this.selectedElement)return;const t=this.getElementInfo(this.selectedElement);let e=this.getFilePath(this.selectedElement);const n=this.selectedElement.getBoundingClientRect();this.selectedTooltip.addEventListener("click",(t=>{e&&this.postMessage("fs-open",e),t.preventDefault(),t.stopPropagation()})),this.selectedTooltip.textContent="\u2713 "+t;let o=n.left-8,r=n.top-this.selectedTooltip.offsetHeight-8;0>o&&(o=8),0>r&&(r=n.top+8),this.selectedTooltip.style.left=o+"px",this.selectedTooltip.style.top=r+"px"}showActionPanel(){this.removeActionPanel();const t=this.selectedElement.getBoundingClientRect();this.actionPanel=document.createElement("div"),this.actionPanel.className="div-selector-actions";let e=t.right-180,n=t.top+6;e+180>window.innerWidth&&(e=t.left-180-8),0>e&&(e=8),n+40>window.innerHeight&&(n=window.innerHeight-40-8),0>n&&(n=8),this.actionPanel.style.left=e+"px",this.actionPanel.style.top=n+"px",[{text:"\ud83d\udccb",action:()=>this.copySelector(this.selectedElement)},{text:"x",action:()=>this.clearSelection()}].forEach((t=>{const e=document.createElement("button");e.className="div-selector-btn "+(t.class||""),e.textContent=t.text,e.onclick=t.action,this.actionPanel.appendChild(e)})),document.body.appendChild(this.actionPanel)}updateActionPanelPosition(){if(!this.actionPanel||!this.selectedElement)return;const t=this.selectedElement.getBoundingClientRect(),e=this.actionPanel.offsetWidth,n=this.actionPanel.offsetHeight;let o=t.right-e+8,r=t.top-8;o+e>window.innerWidth&&(o=t.left-e-8),0>o&&(o=8),r+n>window.innerHeight&&(r=window.innerHeight-n-8),0>r&&(r=8),this.actionPanel.style.left=o+"px",this.actionPanel.style.top=r+"px"}clearSelection(){this.selectedElement=null,this.selectedOverlay&&(this.selectedOverlay.remove(),this.selectedOverlay=null),this.selectedTooltip&&(this.selectedTooltip.remove(),this.selectedTooltip=null),this.removeActionPanel()}getElementInfo(t){const e=t.getBoundingClientRect();let n=t.getAttribute("vref");return n||(n=t.closest("[vref]").getAttribute("vref"),n+="."+t.tagName.toLowerCase()),`${n} (${Math.round(e.width)}\xd7${Math.round(e.height)})`}getFilePath(t){let e=t.getAttribute("vref");return e||(e=t.closest("[vref]").getAttribute("vref")),e&&(e="/ui"+e+".html"),e}copySelector(t){let e=this.getFilePath(t);dn(e).then((()=>{this.showNotification("\ud83d\udccb CSS\u9009\u62e9\u5668\u5df2\u590d\u5236\u5230\u526a\u8d34\u677f")}))}copyXPath(t){const e=this.generateXPath(t);dn(e).then((()=>{this.showNotification("\ud83d\udd0d XPath\u5df2\u590d\u5236\u5230\u526a\u8d34\u677f")}))}viewStyles(t){const e=window.getComputedStyle(t);let n="\ud83d\udcca \u91cd\u8981\u6837\u5f0f\u5c5e\u6027:\n\n";["display","position","width","height","margin","padding","background-color","color","font-size","border","z-index","opacity"].forEach((t=>{n+=`${t}: ${e.getPropertyValue(t)}\n`})),alert(n)}showNotification(t){const e=document.createElement("div");e.style.cssText=`\n position: fixed;\n top: 20px;\n right: 20px;\n background: linear-gradient(135deg, #28a745, #20c997);\n color: white;\n padding: 12px 18px;\n border-radius: 8px;\n z-index: ${this.options.zIndex+10};\n font-size: 14px;\n box-shadow: 0 4px 12px rgba(0,0,0,0.2);\n transform: translateX(100%);\n transition: transform 0.3s ease;\n `,e.textContent=t,document.body.appendChild(e),setTimeout((()=>{e.style.transform="translateX(0)"}),100),setTimeout((()=>{e.style.transform="translateX(100%)",setTimeout((()=>{e.remove()}),300)}),2500)}generateXPath(t){if(t.id)return`//*[@id="${t.id}"]`;const e=[];for(;t&&t.nodeType===Node.ELEMENT_NODE;){let n=0,o=!1,r=!1;for(let e=t.previousSibling;e;e=e.previousSibling)e.nodeType===Node.ELEMENT_NODE&&e.nodeName===t.nodeName&&(r=!0,n++);for(let e=t.nextSibling;e&&!o;e=e.nextSibling)e.nodeType===Node.ELEMENT_NODE&&e.nodeName===t.nodeName&&(o=!0);const i=t.nodeName.toLowerCase(),s=r||o?`[${n+1}]`:"";if(e.unshift(i+s),(t=t.parentNode)===document.body)break}return e.length?"/"+e.join("/"):null}removeOverlay(){this.overlay&&(this.overlay.remove(),this.overlay=null)}removeTooltip(){this.tooltip&&(this.tooltip.remove(),this.tooltip=null)}removeActionPanel(){this.actionPanel&&(this.actionPanel.remove(),this.actionPanel=null)}}let mn=!1,wn=null;const bn=(t,e)=>{mn&&("string"!=typeof e&&"number"!=typeof e||(e={value:e}),window.parent.postMessage(Object.assign({type:t,from:"vdev"},e),"*"))};!async function(){const t=document.createElement("style");t.innerHTML="\n [vref] {\n display: block;\n }\n [vparsing] {\n display: none;\n -webkit-text-fill-color: transparent;\n }\n vslot, vrouter {\n display: block;\n }\n",document.head.firstChild?document.head.insertBefore(t,document.head.firstChild):document.head.appendChild(t);const e=[],n=t=>{if(!t.isConnected)return;let n=t.getAttribute("vdelay");if(n){let o=e[n];o&&o(t)}};function o(t,e){const n=Function("sandbox",t=`with (sandbox) { ${t} }`);let o={data:null,key:null};const r=t=>new Proxy(t,{has:(t,e)=>!0,get(t,e,n){if(e===Symbol.unscopables)return;let i=Reflect.get(t,e,n);return o.data=t,o.key=e,"object"==typeof i&&i?r(i):i},set:(t,e,n,o)=>!1});return n(r(e)),o}new MutationObserver((function(t,e){t.forEach((function(t){for(let e of t.addedNodes)1===e.nodeType&&(n(e),e.querySelectorAll("*[vdelay]").forEach(n))}))})).observe(document.body,{attributes:!1,childList:!0,subtree:!0,characterData:!1});const r=/{{|}}/g,i=/^(\s*(\w+)\s+in\s+|\((\w+),\s*(\w+)\)\s+in\s+)([\w\?\$\.\[\]\(\)'"]+)$/;window.$vhtml||(window.$vhtml=new class{app=null;scoped=null;vget=on;vproxy=y;t=!0;$router=un.$router;constructor(t){"string"==typeof t?this.app=document.getElementById(t):t instanceof HTMLElement?this.app=t:this.app=document.body,this.app&&(async()=>{let t=await on.FetchUI(window.location.pathname,{},!0);this.scoped=t.env?.scoped||"",t.env?.vdev&&window.self!==window.top&&(mn||(mn=!0,wn=new pn,bn("iframe-loaded"),wn.postMessage=bn,window.addEventListener("keyup",(t=>{"Escape"===t.key&&bn("key-esc")})),setTimeout((()=>{window.$vhtml&&window.$vhtml.$router&&$vhtml.$router.onChange((t=>{bn("url-change",t.fullPath)}))}),100),window.addEventListener("message",(t=>{const e=t.data;if("vhtml"==e.from)switch(e.type){case"reload":window.location.reload();break;case"magic":wn&&wn.isActive?wn.deactivate():wn&&wn.activate()}})))),this.parseRef("scoped",this.app,{},t.env||{},t,!0)})()}async parseDom(t,e={},n){if(n instanceof HTMLElement)throw Error("env error");let o=t.nodeName.toLowerCase();if(3===t.nodeType)return void this.parseTextNode(t,e,n);if(8===t.nodeType)return;if(1!==t.nodeType)return;if(t.hasAttribute("no-vhtml")||t.vparsed)return;let r=t.getAttribute("v-for");if(null!==r)return void this.parseVfor(r,t,e,n);if(-1!==o.indexOf("-")){let r="/"+o.split("-").join("/"),i=t.hasAttribute("single");return this.parseRef(r,t,e,n,null,i),void(t.vparsed=!0)}if(t.getAttribute(":vsrc")){let o=t.getAttribute(":vsrc");t.removeAttribute(":vsrc");let r=Array.from(t.attributes).map((t=>({name:t.name,value:t.value}))),i=Array.from(t.childNodes);return void y.Watch((()=>{delete t.vparsed,t.setAttribute("vparsing","");let s=y.Run(o,e,n);s&&(Array.from(t.attributes).forEach((e=>{t.removeAttribute(e.name)})),t.innerHTML="",r.forEach((e=>{t.setAttribute(e.name,e.value)})),i.forEach((e=>{t.appendChild(e.cloneNode(!0))})),this.parseRef(s,t,e,n,null,!1),t.vparsed=!0)}))}if(t.getAttribute("vsrc")){let o=t.hasAttribute("single");return this.parseRef(t.getAttribute("vsrc"),t,e,n,null,o),void(t.vparsed=!0)}if("div"===o&&t.getAttribute("v-html")){let o=t.getAttribute("v-html");return t.removeAttribute("v-html"),t.innerHTML="",this.parseAttrs(t,e,n),t.vparsed=!0,void y.Watch((()=>{let r=y.Run(o,e,n);t.innerHTML=r;let i=this.parseVif(Array.from(t.childNodes),e,n);for(let t of i)this.parseDom(t,e,n)}))}if("vslot"===o)return this.parseSlots(t,e,n),void(t.vparsed=!0);if("vrouter"===o)return this.parseAttrs(t,e,n),void un.$router.ParseVrouter(this,t,n);this.parseAttrs(t,e,n);let i=this.parseVif(Array.from(t.childNodes),e,n);for(let s of i)this.parseDom(s,e,n);t.vparsed=!0}onMountedRun(t,n,o=!0){if(o){if(t.isConnected)return void n(t);let o=e.push((t=>{t.removeAttribute("vdelay"),n(t)}));return void t.setAttribute("vdelay",o-1)}t.isConnected&&n(t);let r=e.push(n);t.setAttribute("vdelay",r-1)}AllENVs={};async parseRef(t,e,n,o,r,i=!1){e.setAttribute("vparsing","");let s=o,a=e.getAttribute("vrefof"),c=e.closest(`*[vref='${a}']`);c&&(o=c.$env),!r&&t&&(t.endsWith(".html")||(t+=".html"),r=await on.FetchUI(t,o,e.hasAttribute("scoped"))),o=Object.assign({},o,r?.env||{}),e.$env=o,e.$vsrc=t,o.$router=un.$router,o.$emit=(t,...n)=>{if(t=t.toLowerCase(),!e.$vevent)return;let o=e.$vevent[t];o&&"function"==typeof o&&o(...n)};let l=await this.setupRef(e,n,s,r,i);i?this.parseAttrs(e,l,o,r?.customAttrs):this.parseAttrs(e,n,s,r?.customAttrs);let u=this.parseVif(Array.from(e.childNodes),l,o);for(let f of u)this.parseDom(f,l,o);e.removeAttribute("vparsing"),this.mountRef(e,l,o,r)}async setupRef(t,e,n,r,i=!1){let s=y.Wrap({});if(r.setup){let e=r.setup.innerHTML;e=await y.ParseImport(e,s,t.$env,t.$vsrc),await y.AsyncRun(e,s,t.$env,{$node:t})}if(t.$refScope=e,t.$refData=s,i)return s;if(!t.$refSlots){let e=y.Wrap({});t.childNodes.forEach((t=>{let n=t.getAttribute?t.getAttribute("vslot"):"";n=n||"",e[n]||(e[n]=[]),e[n].push(t)})),t.$refSlots=e}t.innerHTML="";let a=r.body.cloneNode(!0);t.append(...a.childNodes),Object.keys(s).forEach((r=>{const i=hn.CamelToKebabCase(r);if("boolean"==typeof s[r]?(t.hasAttribute(r)||t.hasAttribute(i))&&(s[r]=!0):t.hasAttribute(r)?(s[r]=t.getAttribute(r),t.removeAttribute(r)):t.hasAttribute(i)&&(s[r]=t.getAttribute(i),t.removeAttribute(i)),t.hasAttribute(":"+r)||t.hasAttribute(":"+i)){let o=t.getAttribute(":"+r)||t.getAttribute(":"+i);t.removeAttribute(":"+r),t.removeAttribute(":"+i),delete s[r],o?y.Watch((()=>y.Run(o,e,n)),(()=>{s[r]=y.Run(o,e,n)}),{deep:!0}):y.Watch((()=>e[r]),(()=>{s[r]=e[r]}),{deep:!0})}if(t.hasAttribute("v:"+r)||t.hasAttribute("v:"+i)){let n=t.getAttribute("v:"+r)||t.getAttribute("v:"+i);t.removeAttribute("v:"+r),t.removeAttribute("v:"+i),n||(n=r),delete s[r],y.Watch((()=>o(n,e)),(t=>{t&&t.data&&t.key&&(s[r]=t.data[t.key])})),y.Watch((()=>s[r]),(()=>{let t=o(n,e);t&&t.data&&t.key&&(t.data[t.key]=s[r])}))}}));let c=Array.from(a.attributes);return c=c.filter((e=>!this.parseAttr(t,e.name,e.value,s,n)||(a.removeAttribute(e.name),!1))),c.forEach((e=>{if("class"===e.name)t.classList.add(...e.value.trim().split(/\s+/));else if("style"===e.name){let n=e.value.split(";");for(let e of n){let n=e.split(":");if(2===n.length&&!t.style[n[0]]){let e=n[0].trim();e.startsWith("--")?t.style.setProperty(e,n[1].trim()):t.style[e]=n[1].trim()}}}else t.getAttribute(e.name)||t.setAttribute(e.name,e.value)})),s}async mountRef(t,e,n,o){for(let r of o.scripts)r.hasAttribute("active")?this.onMountedRun(t,(()=>{y.AsyncRun(r.innerHTML,e,n,{$node:t,$watch:y.Watch})}),!1):y.AsyncRun(r.innerHTML,e,n,{$node:t,$watch:y.Watch})}parseAttrs(t,e,n,o){if("A"===t.nodeName&&this.parseAHref(t,e,n),Array.from(t.attributes).forEach((o=>{this.parseAttr(t,o.name,o.value,e,n)&&t.removeAttribute(o.name)})),o&&Object.keys(o).forEach((e=>{this.parseAttr(t,e,o[e],t.$refData,n)})),t.hasAttribute("v-show")){let o=t.getAttribute("v-show"),r=t.style.display;y.Watch((()=>{let i=y.Run(o,e,n);t.style.display=i?r:"none"}))}}parseAHref(t,e,n){if(!t.hasAttribute("href")&&!t.hasAttribute(":href"))return;y.Watch((()=>{let o=t.getAttribute("href");if(t.hasAttribute(":href")){let r=t.getAttribute(":href");t.removeAttribute(":href"),o=y.Run(r,e,n)}if(o&&!o.startsWith("#")&&!o.startsWith("http"))if(o.startsWith("@"))o=o.replaceAll("//","/"),t.setAttribute("href",o.slice(1));else if(o){let e=n?.scoped;e&&(o=e+o),t.setAttribute("href",o)}}));const o=e=>{let n=e?.fullPath;t.getAttribute("href")===n?t.setAttribute("active",""):t.removeAttribute("active")};o(un.$router.current),un.$router.onChange(o)}parseAttr(t,e,n,r,i){if(e.startsWith(":")){let o=e.slice(1);return"class"===o||"style"===o?this.handleStyle(t,o,n,r,i):y.Watch((()=>{let e;e=n?y.Run(n,r,i):r[o],hn.SetAttr(t,o,e)})),!0}if(e.startsWith("@"))return this.handleEvent(t,e,n,r,i),!0;if(e.indexOf("!")>-1);else if(e.startsWith("v:")){let e=o(n,r);if(e&&e.data&&e.key){let n=e.key,o=e.data;return hn.BindInputDomValue(t,o,n,y.Watch)}}else if("vdom"===e){let e=o(n,r);return e&&e.data&&e.key&&(e.data[e.key]=t),!0}return!1}handleStyle(t,e,n,o,r){let i="";y.Watch((()=>{let s=y.Run(n,o,r);if("function"==typeof s&&(s=s()),"class"===e){if(i&&(t.classList.remove(...i.split(/\s+/)),i=""),s instanceof Array)i="",s.forEach((t=>{if("string"==typeof t&&t.length)i+=" "+t;else if("object"==typeof t)for(let e in t)t[e]&&(i+=" "+e)}));else if("string"==typeof s&&s.length)i=s.trim();else if("object"==typeof s){i="";for(let t in s)s[t]&&(i+=" "+t)}i=i.trim(),i&&t.classList.add(...i.split(/\s+/))}else if("style"===e){if(i)if("object"==typeof i)for(let e in i)e.startsWith("--")?t.style.removeProperty(e):t.style[e]="";else if("string"==typeof i){let e=i.split(";");for(let n of e){let e=n.split(":");2===e.length&&(e[0].trim().startsWith("--")?t.style.removeProperty(e[0].trim()):t.style[e[0].trim()]="")}}if("object"==typeof s)for(let e in s)e.startsWith("--")?t.style.setProperty(e,s[e]):t.style[e]=s[e];else if("string"==typeof s){let e=s.split(";");for(let n of e){let e=n.split(":");2===e.length&&(e[0].trim().startsWith("--")?t.style.setProperty(e[0].trim(),e[1].trim()):t.style[e[0].trim()]=e[1].trim())}}i=s}}))}handleEvent(t,e,n,o,r){let i=e.slice(1).split("."),s={self:!1,prevent:!1,stop:!1},a=i[0];if("mounted"===a)this.onMountedRun(t,(t=>{let e=y.Run(n,o,r);"function"==typeof e&&e(t)}),!1);else if("outerclick"===a){let e=t=>{let e=y.Run(n,o,r,{$event:t});"function"==typeof e&&e(t)};hn.AddClicker(t,"outer",e)}else if(-1!==hn.EventsList.indexOf(a)){"keydown"!==a&&"keyup"!==a&&"keypress"!==a||"INPUT"!==t.tagName&&"TEXTAREA"!==t.tagName&&t.setAttribute("tabindex","0");let e=t=>{let e=y.Run(n,o,r,{$event:t});"function"==typeof e&&e(t)};i.slice(1).forEach((i=>{if(i.startsWith("delay")){let s=i.slice(5);s=s?s.endsWith("ms")?+s.slice(0,-2):s.endsWith("s")?1e3*+s.slice(0,-1):+s:1e3,isNaN(s)&&(s=1e3),e=e=>{let i=t["_"+a];i&&"number"==typeof i&&clearTimeout(i),t["_"+a]=setTimeout((()=>{let t=y.Run(n,o,r,{$event:e});"function"==typeof t&&t(e)}),s)}}s[i]=!0})),t.addEventListener(a,(t=>{(1>=i.length||"keydown"!==a&&"keyup"!=a&&"keypress"!=a||i[1]===t.key?.toLowerCase())&&(s.self&&t.currentTarget!==t.target||(s.prevent&&t.preventDefault(),s.stop&&t.stopPropagation(),e(t)))}))}else t.$vevent=t.$vevent||{},t.$vevent[a]=(...t)=>{let e=y.Run(n,o,r,{});"function"==typeof e&&e(...t)}}parseTextNode(t,e,n){let o,i=t.nodeValue.trim();if(!i)return;let s=0,a=-1,c=[];for(;null!==(o=r.exec(i));)if("{{"===o[0])a=o.index;else if("}}"===o[0]&&a>=0){s!==a&&c.push(i.slice(s,a)),c.push("");let r=i.slice(a+2,o.index),l=c.length;a=-1,s=o.index+2,y.Watch((()=>{c[l-1]=y.Run(r,e,n),"object"==typeof c[l-1]&&(c[l-1]=JSON.stringify(c[l-1])),t.nodeValue=c.join("")}))}c.push(i.slice(s)),t.nodeValue=c.join("")}vforDomCache={};parseVfor(t,e,n,o){e.removeAttribute("v-for");let r=i.exec(t);if(6===r?.length){let t=document.createElement("div");t.style.display="none";let i=y.GenUniqueID();this.vforDomCache[i]={},e.parentNode.replaceChild(t,e),y.Watch((()=>{let s=r[3]||r[2],a=r[4],c=y.Run(r[5],n,o),l=this.vforDomCache[i],u=new Set;if("function"==typeof c?c=c():"number"==typeof c&&(c=Array.from({length:c},((t,e)=>e))),null==c&&(c=[]),c.length,"object"==typeof c){let r=Object.keys(c),f=[];for(let t in r){let e=r[t],n="";n=c[e]&&c[e][y.DataID]?c[e][y.DataID]:e+"."+c[e],n=i+"."+n,u.add(n),f.push({k:e,vfk:n,val:c[e]})}for(let t of Object.keys(l))u.has(t)||(l[t]instanceof Array?l[t].forEach((t=>t.remove())):l[t].remove(),delete l[t]);let h=t;for(let i=f.length-1;i>=0;i--){let{k:r,vfk:c,val:u}=f[i],d=l[c];if(d){a&&(d.$vforData[a]="0"===r?0:+r||r),d.isConnected&&(d.nextSibling!==h&&t.parentNode.insertBefore(d,h),h=d);continue}let p=e.cloneNode(!0);l[c]=p;let m={[s]:u};a&&(m[a]="0"===r?0:+r||r),m=y.Wrap(m,n),p.$vforData=m,t.parentNode.insertBefore(p,h);let w=e.getAttribute("v-if");if(!w){this.parseDom(p,m,o),h=p;continue}p.removeAttribute("v-if");let b=-1;b=y.Watch((()=>{let e=l[c];if(e)if(y.Run(w,m,o)){if(e.vparsed||this.parseDom(e,m,o),!e.isConnected){let n=!1,o=t;for(let t in l)if(t!==c){if(n&&l[t].isConnected){o=l[t];break}}else n=!0;t.parentNode.insertBefore(e,o)}}else e.isConnected?e.remove():this.onMountedRun(e,(t=>{e.remove()}));else y.Cancel(b)})),p.isConnected&&(h=p)}}}))}}parseVif(t,e,n){let o={now:document.createElement("div"),conds:[],doms:[]};const r=t=>{let o={now:t.now,conds:t.conds,doms:t.doms},r=[];for(let e in o.conds){let t=o.conds[e];t=""===t?"true":"Boolean("+t+")",r.push(t)}let i=`let res = [${r.join(",")}]\n return res.indexOf(true)`;y.Watch((()=>{let t=y.Run(i,e,n),r=o.doms[t];return r||(r=document.createElement("div"),r.style.display="none"),r}),(t=>{t&&(this.onMountedRun(o.now,(e=>{e.replaceWith(t),o.now=t})),t?.vparsed||this.parseDom(t,e,n))}))};let i=t.filter((t=>!(t.getAttribute&&!t.getAttribute("v-for")&&(null!==t.getAttribute("v-if")?(o.conds.length>0&&(r(o),o={now:document.createElement("div"),conds:[],doms:[]}),t.replaceWith(o.now),o.conds.push(t.getAttribute("v-if")),t.removeAttribute("v-if"),o.doms.push(t),1):null!==t.getAttribute("v-else-if")?(o.conds.push(t.getAttribute("v-else-if")),t.removeAttribute("v-else-if"),o.doms.push(t),t.remove(),1):null!==t.getAttribute("v-else")&&(o.conds.push(""),t.removeAttribute("v-else"),o.doms.push(t),t.remove(),1)))));return o.conds.length>0&&r(o),i}parseSlots(t,e,n){let o=t.getAttribute("vrefof"),r=t.closest(`*[vref='${o}']`);if(!r)return void this.onMountedRun(t,(t=>{this.parseSlots(t,e,n)}));for(;;){let t=r?.parentNode.closest("*[vref]");if(!t)break;if(t.getAttribute("vref")!==o)break;r=t}let i=t.getAttribute("name")||"";if(t.getAttribute(":name")){let o=t.getAttribute(":name");t.removeAttribute(":name"),i=y.Run(o,e,n)}return t.originContent||(t.$originContent=Array.from(t.childNodes),t.innerHTML=""),t.$slotCache={},y.Watch((()=>{let o=r.$refSlots||{},s=r.$refScope||{},a=o[i];if(a&&a.length>0){let o=a[0].hashID;if(o){if(t.$slotCache[o])return t.innerHTML="",void t.append(...t.$slotCache[o])}else o=y.GenUniqueID(),a[0].hashID=o;t.innerHTML="",a=a.map((t=>t.cloneNode(!0))),t.append(...a);let r=s;if(null!==t.getAttribute("vbind")){let n=t.getAttribute("vbind").split(",").map((t=>t.trim()));r=y.Wrap({}),n.forEach((t=>{e.hasOwnProperty(t)&&(r[t]=e[t])})),y.SetDataRoot(r,s)}let i="";a.find((t=>!(!t.getAttribute||!t.getAttribute("vrefof")||(i=t.getAttribute("vrefof"),0))));let c=n;if(i){let e=t.closest(`*[vref='${i}']`);c=e?.$env||n}a=this.parseVif(a,r,c),a.forEach((t=>this.parseDom(t,r,c))),t.$slotCache[o]=a}else{t.innerHTML="",t.append(...t.$originContent);let o=!1;t.$originContent.forEach((t=>{t.hasAttribute&&t.vparsed&&(o=!0)})),o||(t.$originContent=this.parseVif(t.$originContent,e,n),t.$originContent.forEach((t=>this.parseDom(t,e,n))))}})),this.parseAttrs(t,e,n),t}}(document.body))}()},"function"==typeof define&&define.amd?define(t):t(); \ No newline at end of file diff --git a/ui/page/index.html b/ui/page/index.html index 8bd13af..b4128ca 100644 --- a/ui/page/index.html +++ b/ui/page/index.html @@ -89,7 +89,7 @@ diff --git a/ui/page/login.html b/ui/page/login.html index 8d84962..366be36 100644 --- a/ui/page/login.html +++ b/ui/page/login.html @@ -409,15 +409,15 @@ - - -
- 忘记密码? -
{{ signInError }}
- 登 录 -
-
+ +
+ + + + 忘记密码? +
{{ signInError }}
+ 登 录 +
@@ -501,12 +501,6 @@ return true; }; - // v-form 配置项 (用户名登录) - signInUsernameItems = [ - {name: 'username', placeholder: '用户名', required: true, validate: validateUsername}, - {name: 'password', placeholder: '密码', type: 'password', required: true, validate: validatePassword} - ]; - // 常用国家/地区代码 - 转换为 v-select 格式 regions = [ {value: '+86', label: '+86 中国'}, @@ -659,9 +653,13 @@ $message.success('注册成功!'); signUpForm = {username: '', phone: '', verifyCode: '', password: '', region: '+86'}; + signUpLoading = false; switchToSignIn(); } catch (error) { signUpError = error.message || '注册失败,请重试。'; + if (signUpError.indexOf("Duplicate entry") >= 0) { + signUpError = '用户名重复' + } $message.warning(signUpError); } finally { signUpLoading = false; @@ -676,9 +674,8 @@ try { let loginData = {}; if (loginType === 'username') { - // v-form 提交时已经通过了基本验证,但 double check 也没坏处 if (validateUsername(signInForm.username) !== true) return; - if (validatePassword(signInForm.password) !== true) return; + // if (validatePassword(signInForm.password) !== true) return; loginData = {username: signInForm.username, code: btoa(signInForm.password), type: 'username'}; } else { if (validatePhone(signInForm.phone) !== true) return; @@ -687,9 +684,17 @@ } signInLoading = true; - await $axios.post('/api/token', loginData, {noretry: true}); - $message.success('登录成功!'); - $router.push(redirect); + const loginResponse = await $axios.post('/api/user/login', { + username: signInForm.username, + code: btoa(signInForm.password), + }, {noretry: true}); + if (loginResponse && typeof loginResponse === 'string') { + localStorage.setItem('refresh', loginResponse) + window.location.href = redirect + } else { + console.warn('登录失败,服务器返回异常数据', loginResponse); + $message.warning('服务器异常'); + } } catch (error) { signInError = error.message || '登录失败,请重试'; $message.warning(signInError); diff --git a/ui/root.html b/ui/root.html index 4120b43..5b62b06 100644 --- a/ui/root.html +++ b/ui/root.html @@ -4,7 +4,8 @@ oa - + + diff --git a/ui/vhtml/axios.min.js b/ui/vhtml/axios.min.js new file mode 100644 index 0000000..c0d0b27 --- /dev/null +++ b/ui/vhtml/axios.min.js @@ -0,0 +1,3 @@ +/*! Axios v1.10.0 Copyright (c) 2025 Matt Zabriskie and contributors */ +function e(e,t){return function(){return e.apply(t,arguments)}}const{toString:t}=Object.prototype,{getPrototypeOf:n}=Object,{iterator:r,toStringTag:o}=Symbol,s=(i=Object.create(null),e=>{const n=t.call(e);return i[n]||(i[n]=n.slice(8,-1).toLowerCase())});var i;const a=e=>(e=e.toLowerCase(),t=>s(t)===e),c=e=>t=>typeof t===e,{isArray:l}=Array,u=c("undefined");const f=a("ArrayBuffer");const d=c("string"),p=c("function"),h=c("number"),m=e=>null!==e&&"object"==typeof e,y=e=>{if("object"!==s(e))return!1;const t=n(e);return!(null!==t&&t!==Object.prototype&&null!==Object.getPrototypeOf(t)||o in e||r in e)},b=a("Date"),g=a("File"),w=a("Blob"),E=a("FileList"),O=a("URLSearchParams"),[R,S,T,A]=["ReadableStream","Request","Response","Headers"].map(a);function v(e,t,{allOwnKeys:n=!1}={}){if(null==e)return;let r,o;if("object"!=typeof e&&(e=[e]),l(e))for(r=0,o=e.length;r0;)if(r=n[o],t===r.toLowerCase())return r;return null}const C="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:global,j=e=>!u(e)&&e!==C;const N=(U="undefined"!=typeof Uint8Array&&n(Uint8Array),e=>U&&e instanceof U);var U;const P=a("HTMLFormElement"),_=(({hasOwnProperty:e})=>(t,n)=>e.call(t,n))(Object.prototype),F=a("RegExp"),L=(e,t)=>{const n=Object.getOwnPropertyDescriptors(e),r={};v(n,((n,o)=>{let s;!1!==(s=t(n,o,e))&&(r[o]=s||n)})),Object.defineProperties(e,r)};const B=a("AsyncFunction"),k=(D="function"==typeof setImmediate,q=p(C.postMessage),D?setImmediate:q?(I=`axios@${Math.random()}`,M=[],C.addEventListener("message",(({source:e,data:t})=>{e===C&&t===I&&M.length&&M.shift()()}),!1),e=>{M.push(e),C.postMessage(I,"*")}):e=>setTimeout(e));var D,q,I,M;const z="undefined"!=typeof queueMicrotask?queueMicrotask.bind(C):"undefined"!=typeof process&&process.nextTick||k,H={isArray:l,isArrayBuffer:f,isBuffer:function(e){return null!==e&&!u(e)&&null!==e.constructor&&!u(e.constructor)&&p(e.constructor.isBuffer)&&e.constructor.isBuffer(e)},isFormData:e=>{let t;return e&&("function"==typeof FormData&&e instanceof FormData||p(e.append)&&("formdata"===(t=s(e))||"object"===t&&p(e.toString)&&"[object FormData]"===e.toString()))},isArrayBufferView:function(e){let t;return t="undefined"!=typeof ArrayBuffer&&ArrayBuffer.isView?ArrayBuffer.isView(e):e&&e.buffer&&f(e.buffer),t},isString:d,isNumber:h,isBoolean:e=>!0===e||!1===e,isObject:m,isPlainObject:y,isReadableStream:R,isRequest:S,isResponse:T,isHeaders:A,isUndefined:u,isDate:b,isFile:g,isBlob:w,isRegExp:F,isFunction:p,isStream:e=>m(e)&&p(e.pipe),isURLSearchParams:O,isTypedArray:N,isFileList:E,forEach:v,merge:function e(){const{caseless:t}=j(this)&&this||{},n={},r=(r,o)=>{const s=t&&x(n,o)||o;y(n[s])&&y(r)?n[s]=e(n[s],r):y(r)?n[s]=e({},r):l(r)?n[s]=r.slice():n[s]=r};for(let e=0,t=arguments.length;e(v(n,((n,o)=>{r&&p(n)?t[o]=e(n,r):t[o]=n}),{allOwnKeys:o}),t),trim:e=>e.trim?e.trim():e.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,""),stripBOM:e=>(65279===e.charCodeAt(0)&&(e=e.slice(1)),e),inherits:(e,t,n,r)=>{e.prototype=Object.create(t.prototype,r),e.prototype.constructor=e,Object.defineProperty(e,"super",{value:t.prototype}),n&&Object.assign(e.prototype,n)},toFlatObject:(e,t,r,o)=>{let s,i,a;const c={};if(t=t||{},null==e)return t;do{for(s=Object.getOwnPropertyNames(e),i=s.length;i-- >0;)a=s[i],o&&!o(a,e,t)||c[a]||(t[a]=e[a],c[a]=!0);e=!1!==r&&n(e)}while(e&&(!r||r(e,t))&&e!==Object.prototype);return t},kindOf:s,kindOfTest:a,endsWith:(e,t,n)=>{e=String(e),(void 0===n||n>e.length)&&(n=e.length),n-=t.length;const r=e.indexOf(t,n);return-1!==r&&r===n},toArray:e=>{if(!e)return null;if(l(e))return e;let t=e.length;if(!h(t))return null;const n=new Array(t);for(;t-- >0;)n[t]=e[t];return n},forEachEntry:(e,t)=>{const n=(e&&e[r]).call(e);let o;for(;(o=n.next())&&!o.done;){const n=o.value;t.call(e,n[0],n[1])}},matchAll:(e,t)=>{let n;const r=[];for(;null!==(n=e.exec(t));)r.push(n);return r},isHTMLForm:P,hasOwnProperty:_,hasOwnProp:_,reduceDescriptors:L,freezeMethods:e=>{L(e,((t,n)=>{if(p(e)&&-1!==["arguments","caller","callee"].indexOf(n))return!1;const r=e[n];p(r)&&(t.enumerable=!1,"writable"in t?t.writable=!1:t.set||(t.set=()=>{throw Error("Can not rewrite read-only method '"+n+"'")}))}))},toObjectSet:(e,t)=>{const n={},r=e=>{e.forEach((e=>{n[e]=!0}))};return l(e)?r(e):r(String(e).split(t)),n},toCamelCase:e=>e.toLowerCase().replace(/[-_\s]([a-z\d])(\w*)/g,(function(e,t,n){return t.toUpperCase()+n})),noop:()=>{},toFiniteNumber:(e,t)=>null!=e&&Number.isFinite(e=+e)?e:t,findKey:x,global:C,isContextDefined:j,isSpecCompliantForm:function(e){return!!(e&&p(e.append)&&"FormData"===e[o]&&e[r])},toJSONObject:e=>{const t=new Array(10),n=(e,r)=>{if(m(e)){if(t.indexOf(e)>=0)return;if(!("toJSON"in e)){t[r]=e;const o=l(e)?[]:{};return v(e,((e,t)=>{const s=n(e,r+1);!u(s)&&(o[t]=s)})),t[r]=void 0,o}}return e};return n(e,0)},isAsyncFn:B,isThenable:e=>e&&(m(e)||p(e))&&p(e.then)&&p(e.catch),setImmediate:k,asap:z,isIterable:e=>null!=e&&p(e[r])};function J(e,t,n,r,o){Error.call(this),Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):this.stack=(new Error).stack,this.message=e,this.name="AxiosError",t&&(this.code=t),n&&(this.config=n),r&&(this.request=r),o&&(this.response=o,this.status=o.status?o.status:null)}H.inherits(J,Error,{toJSON:function(){return{message:this.message,name:this.name,description:this.description,number:this.number,fileName:this.fileName,lineNumber:this.lineNumber,columnNumber:this.columnNumber,stack:this.stack,config:H.toJSONObject(this.config),code:this.code,status:this.status}}});const W=J.prototype,K={};["ERR_BAD_OPTION_VALUE","ERR_BAD_OPTION","ECONNABORTED","ETIMEDOUT","ERR_NETWORK","ERR_FR_TOO_MANY_REDIRECTS","ERR_DEPRECATED","ERR_BAD_RESPONSE","ERR_BAD_REQUEST","ERR_CANCELED","ERR_NOT_SUPPORT","ERR_INVALID_URL"].forEach((e=>{K[e]={value:e}})),Object.defineProperties(J,K),Object.defineProperty(W,"isAxiosError",{value:!0}),J.from=(e,t,n,r,o,s)=>{const i=Object.create(W);return H.toFlatObject(e,i,(function(e){return e!==Error.prototype}),(e=>"isAxiosError"!==e)),J.call(i,e.message,t,n,r,o),i.cause=e,i.name=e.name,s&&Object.assign(i,s),i};function V(e){return H.isPlainObject(e)||H.isArray(e)}function $(e){return H.endsWith(e,"[]")?e.slice(0,-2):e}function X(e,t,n){return e?e.concat(t).map((function(e,t){return e=$(e),!n&&t?"["+e+"]":e})).join(n?".":""):t}const G=H.toFlatObject(H,{},null,(function(e){return/^is[A-Z]/.test(e)}));function Q(e,t,n){if(!H.isObject(e))throw new TypeError("target must be an object");t=t||new FormData;const r=(n=H.toFlatObject(n,{metaTokens:!0,dots:!1,indexes:!1},!1,(function(e,t){return!H.isUndefined(t[e])}))).metaTokens,o=n.visitor||l,s=n.dots,i=n.indexes,a=(n.Blob||"undefined"!=typeof Blob&&Blob)&&H.isSpecCompliantForm(t);if(!H.isFunction(o))throw new TypeError("visitor must be a function");function c(e){if(null===e)return"";if(H.isDate(e))return e.toISOString();if(H.isBoolean(e))return e.toString();if(!a&&H.isBlob(e))throw new J("Blob is not supported. Use a Buffer instead.");return H.isArrayBuffer(e)||H.isTypedArray(e)?a&&"function"==typeof Blob?new Blob([e]):Buffer.from(e):e}function l(e,n,o){let a=e;if(e&&!o&&"object"==typeof e)if(H.endsWith(n,"{}"))n=r?n:n.slice(0,-2),e=JSON.stringify(e);else if(H.isArray(e)&&function(e){return H.isArray(e)&&!e.some(V)}(e)||(H.isFileList(e)||H.endsWith(n,"[]"))&&(a=H.toArray(e)))return n=$(n),a.forEach((function(e,r){!H.isUndefined(e)&&null!==e&&t.append(!0===i?X([n],r,s):null===i?n:n+"[]",c(e))})),!1;return!!V(e)||(t.append(X(o,n,s),c(e)),!1)}const u=[],f=Object.assign(G,{defaultVisitor:l,convertValue:c,isVisitable:V});if(!H.isObject(e))throw new TypeError("data must be an object");return function e(n,r){if(!H.isUndefined(n)){if(-1!==u.indexOf(n))throw Error("Circular reference detected in "+r.join("."));u.push(n),H.forEach(n,(function(n,s){!0===(!(H.isUndefined(n)||null===n)&&o.call(t,n,H.isString(s)?s.trim():s,r,f))&&e(n,r?r.concat(s):[s])})),u.pop()}}(e),t}function Z(e){const t={"!":"%21","'":"%27","(":"%28",")":"%29","~":"%7E","%20":"+","%00":"\0"};return encodeURIComponent(e).replace(/[!'()~]|%20|%00/g,(function(e){return t[e]}))}function Y(e,t){this._pairs=[],e&&Q(e,this,t)}const ee=Y.prototype;function te(e){return encodeURIComponent(e).replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+").replace(/%5B/gi,"[").replace(/%5D/gi,"]")}function ne(e,t,n){if(!t)return e;const r=n&&n.encode||te;H.isFunction(n)&&(n={serialize:n});const o=n&&n.serialize;let s;if(s=o?o(t,n):H.isURLSearchParams(t)?t.toString():new Y(t,n).toString(r),s){const t=e.indexOf("#");-1!==t&&(e=e.slice(0,t)),e+=(-1===e.indexOf("?")?"?":"&")+s}return e}ee.append=function(e,t){this._pairs.push([e,t])},ee.toString=function(e){const t=e?function(t){return e.call(this,t,Z)}:Z;return this._pairs.map((function(e){return t(e[0])+"="+t(e[1])}),"").join("&")};const re=class{constructor(){this.handlers=[]}use(e,t,n){return this.handlers.push({fulfilled:e,rejected:t,synchronous:!!n&&n.synchronous,runWhen:n?n.runWhen:null}),this.handlers.length-1}eject(e){this.handlers[e]&&(this.handlers[e]=null)}clear(){this.handlers&&(this.handlers=[])}forEach(e){H.forEach(this.handlers,(function(t){null!==t&&e(t)}))}},oe={silentJSONParsing:!0,forcedJSONParsing:!0,clarifyTimeoutError:!1},se={isBrowser:!0,classes:{URLSearchParams:"undefined"!=typeof URLSearchParams?URLSearchParams:Y,FormData:"undefined"!=typeof FormData?FormData:null,Blob:"undefined"!=typeof Blob?Blob:null},protocols:["http","https","file","blob","url","data"]},ie="undefined"!=typeof window&&"undefined"!=typeof document,ae="object"==typeof navigator&&navigator||void 0,ce=ie&&(!ae||["ReactNative","NativeScript","NS"].indexOf(ae.product)<0),le="undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope&&"function"==typeof self.importScripts,ue=ie&&window.location.href||"http://localhost",fe={...Object.freeze({__proto__:null,hasBrowserEnv:ie,hasStandardBrowserWebWorkerEnv:le,hasStandardBrowserEnv:ce,navigator:ae,origin:ue}),...se};function de(e){function t(e,n,r,o){let s=e[o++];if("__proto__"===s)return!0;const i=Number.isFinite(+s),a=o>=e.length;if(s=!s&&H.isArray(r)?r.length:s,a)return H.hasOwnProp(r,s)?r[s]=[r[s],n]:r[s]=n,!i;r[s]&&H.isObject(r[s])||(r[s]=[]);return t(e,n,r[s],o)&&H.isArray(r[s])&&(r[s]=function(e){const t={},n=Object.keys(e);let r;const o=n.length;let s;for(r=0;r{t(function(e){return H.matchAll(/\w+|\[(\w*)]/g,e).map((e=>"[]"===e[0]?"":e[1]||e[0]))}(e),r,n,0)})),n}return null}const pe={transitional:oe,adapter:["xhr","http","fetch"],transformRequest:[function(e,t){const n=t.getContentType()||"",r=n.indexOf("application/json")>-1,o=H.isObject(e);o&&H.isHTMLForm(e)&&(e=new FormData(e));if(H.isFormData(e))return r?JSON.stringify(de(e)):e;if(H.isArrayBuffer(e)||H.isBuffer(e)||H.isStream(e)||H.isFile(e)||H.isBlob(e)||H.isReadableStream(e))return e;if(H.isArrayBufferView(e))return e.buffer;if(H.isURLSearchParams(e))return t.setContentType("application/x-www-form-urlencoded;charset=utf-8",!1),e.toString();let s;if(o){if(n.indexOf("application/x-www-form-urlencoded")>-1)return function(e,t){return Q(e,new fe.classes.URLSearchParams,Object.assign({visitor:function(e,t,n,r){return fe.isNode&&H.isBuffer(e)?(this.append(t,e.toString("base64")),!1):r.defaultVisitor.apply(this,arguments)}},t))}(e,this.formSerializer).toString();if((s=H.isFileList(e))||n.indexOf("multipart/form-data")>-1){const t=this.env&&this.env.FormData;return Q(s?{"files[]":e}:e,t&&new t,this.formSerializer)}}return o||r?(t.setContentType("application/json",!1),function(e,t,n){if(H.isString(e))try{return(t||JSON.parse)(e),H.trim(e)}catch(e){if("SyntaxError"!==e.name)throw e}return(n||JSON.stringify)(e)}(e)):e}],transformResponse:[function(e){const t=this.transitional||pe.transitional,n=t&&t.forcedJSONParsing,r="json"===this.responseType;if(H.isResponse(e)||H.isReadableStream(e))return e;if(e&&H.isString(e)&&(n&&!this.responseType||r)){const n=!(t&&t.silentJSONParsing)&&r;try{return JSON.parse(e)}catch(e){if(n){if("SyntaxError"===e.name)throw J.from(e,J.ERR_BAD_RESPONSE,this,null,this.response);throw e}}}return e}],timeout:0,xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",maxContentLength:-1,maxBodyLength:-1,env:{FormData:fe.classes.FormData,Blob:fe.classes.Blob},validateStatus:function(e){return e>=200&&e<300},headers:{common:{Accept:"application/json, text/plain, */*","Content-Type":void 0}}};H.forEach(["delete","get","head","post","put","patch"],(e=>{pe.headers[e]={}}));const he=pe,me=H.toObjectSet(["age","authorization","content-length","content-type","etag","expires","from","host","if-modified-since","if-unmodified-since","last-modified","location","max-forwards","proxy-authorization","referer","retry-after","user-agent"]),ye=Symbol("internals");function be(e){return e&&String(e).trim().toLowerCase()}function ge(e){return!1===e||null==e?e:H.isArray(e)?e.map(ge):String(e)}function we(e,t,n,r,o){return H.isFunction(r)?r.call(this,t,n):(o&&(t=n),H.isString(t)?H.isString(r)?-1!==t.indexOf(r):H.isRegExp(r)?r.test(t):void 0:void 0)}class Ee{constructor(e){e&&this.set(e)}set(e,t,n){const r=this;function o(e,t,n){const o=be(t);if(!o)throw new Error("header name must be a non-empty string");const s=H.findKey(r,o);(!s||void 0===r[s]||!0===n||void 0===n&&!1!==r[s])&&(r[s||t]=ge(e))}const s=(e,t)=>H.forEach(e,((e,n)=>o(e,n,t)));if(H.isPlainObject(e)||e instanceof this.constructor)s(e,t);else if(H.isString(e)&&(e=e.trim())&&!/^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(e.trim()))s((e=>{const t={};let n,r,o;return e&&e.split("\n").forEach((function(e){o=e.indexOf(":"),n=e.substring(0,o).trim().toLowerCase(),r=e.substring(o+1).trim(),!n||t[n]&&me[n]||("set-cookie"===n?t[n]?t[n].push(r):t[n]=[r]:t[n]=t[n]?t[n]+", "+r:r)})),t})(e),t);else if(H.isObject(e)&&H.isIterable(e)){let n,r,o={};for(const t of e){if(!H.isArray(t))throw TypeError("Object iterator must return a key-value pair");o[r=t[0]]=(n=o[r])?H.isArray(n)?[...n,t[1]]:[n,t[1]]:t[1]}s(o,t)}else null!=e&&o(t,e,n);return this}get(e,t){if(e=be(e)){const n=H.findKey(this,e);if(n){const e=this[n];if(!t)return e;if(!0===t)return function(e){const t=Object.create(null),n=/([^\s,;=]+)\s*(?:=\s*([^,;]+))?/g;let r;for(;r=n.exec(e);)t[r[1]]=r[2];return t}(e);if(H.isFunction(t))return t.call(this,e,n);if(H.isRegExp(t))return t.exec(e);throw new TypeError("parser must be boolean|regexp|function")}}}has(e,t){if(e=be(e)){const n=H.findKey(this,e);return!(!n||void 0===this[n]||t&&!we(0,this[n],n,t))}return!1}delete(e,t){const n=this;let r=!1;function o(e){if(e=be(e)){const o=H.findKey(n,e);!o||t&&!we(0,n[o],o,t)||(delete n[o],r=!0)}}return H.isArray(e)?e.forEach(o):o(e),r}clear(e){const t=Object.keys(this);let n=t.length,r=!1;for(;n--;){const o=t[n];e&&!we(0,this[o],o,e,!0)||(delete this[o],r=!0)}return r}normalize(e){const t=this,n={};return H.forEach(this,((r,o)=>{const s=H.findKey(n,o);if(s)return t[s]=ge(r),void delete t[o];const i=e?function(e){return e.trim().toLowerCase().replace(/([a-z\d])(\w*)/g,((e,t,n)=>t.toUpperCase()+n))}(o):String(o).trim();i!==o&&delete t[o],t[i]=ge(r),n[i]=!0})),this}concat(...e){return this.constructor.concat(this,...e)}toJSON(e){const t=Object.create(null);return H.forEach(this,((n,r)=>{null!=n&&!1!==n&&(t[r]=e&&H.isArray(n)?n.join(", "):n)})),t}[Symbol.iterator](){return Object.entries(this.toJSON())[Symbol.iterator]()}toString(){return Object.entries(this.toJSON()).map((([e,t])=>e+": "+t)).join("\n")}getSetCookie(){return this.get("set-cookie")||[]}get[Symbol.toStringTag](){return"AxiosHeaders"}static from(e){return e instanceof this?e:new this(e)}static concat(e,...t){const n=new this(e);return t.forEach((e=>n.set(e))),n}static accessor(e){const t=(this[ye]=this[ye]={accessors:{}}).accessors,n=this.prototype;function r(e){const r=be(e);t[r]||(!function(e,t){const n=H.toCamelCase(" "+t);["get","set","has"].forEach((r=>{Object.defineProperty(e,r+n,{value:function(e,n,o){return this[r].call(this,t,e,n,o)},configurable:!0})}))}(n,e),t[r]=!0)}return H.isArray(e)?e.forEach(r):r(e),this}}Ee.accessor(["Content-Type","Content-Length","Accept","Accept-Encoding","User-Agent","Authorization"]),H.reduceDescriptors(Ee.prototype,(({value:e},t)=>{let n=t[0].toUpperCase()+t.slice(1);return{get:()=>e,set(e){this[n]=e}}})),H.freezeMethods(Ee);const Oe=Ee;function Re(e,t){const n=this||he,r=t||n,o=Oe.from(r.headers);let s=r.data;return H.forEach(e,(function(e){s=e.call(n,s,o.normalize(),t?t.status:void 0)})),o.normalize(),s}function Se(e){return!(!e||!e.__CANCEL__)}function Te(e,t,n){J.call(this,null==e?"canceled":e,J.ERR_CANCELED,t,n),this.name="CanceledError"}function Ae(e,t,n){const r=n.config.validateStatus;n.status&&r&&!r(n.status)?t(new J("Request failed with status code "+n.status,[J.ERR_BAD_REQUEST,J.ERR_BAD_RESPONSE][Math.floor(n.status/100)-4],n.config,n.request,n)):e(n)}H.inherits(Te,J,{__CANCEL__:!0});const ve=(e,t,n=3)=>{let r=0;const o=function(e,t){e=e||10;const n=new Array(e),r=new Array(e);let o,s=0,i=0;return t=void 0!==t?t:1e3,function(a){const c=Date.now(),l=r[i];o||(o=c),n[s]=a,r[s]=c;let u=i,f=0;for(;u!==s;)f+=n[u++],u%=e;if(s=(s+1)%e,s===i&&(i=(i+1)%e),c-o{o=s,n=null,r&&(clearTimeout(r),r=null),e.apply(null,t)};return[(...e)=>{const t=Date.now(),a=t-o;a>=s?i(e,t):(n=e,r||(r=setTimeout((()=>{r=null,i(n)}),s-a)))},()=>n&&i(n)]}((n=>{const s=n.loaded,i=n.lengthComputable?n.total:void 0,a=s-r,c=o(a);r=s;e({loaded:s,total:i,progress:i?s/i:void 0,bytes:a,rate:c||void 0,estimated:c&&i&&s<=i?(i-s)/c:void 0,event:n,lengthComputable:null!=i,[t?"download":"upload"]:!0})}),n)},xe=(e,t)=>{const n=null!=e;return[r=>t[0]({lengthComputable:n,total:e,loaded:r}),t[1]]},Ce=e=>(...t)=>H.asap((()=>e(...t))),je=fe.hasStandardBrowserEnv?((e,t)=>n=>(n=new URL(n,fe.origin),e.protocol===n.protocol&&e.host===n.host&&(t||e.port===n.port)))(new URL(fe.origin),fe.navigator&&/(msie|trident)/i.test(fe.navigator.userAgent)):()=>!0,Ne=fe.hasStandardBrowserEnv?{write(e,t,n,r,o,s){const i=[e+"="+encodeURIComponent(t)];H.isNumber(n)&&i.push("expires="+new Date(n).toGMTString()),H.isString(r)&&i.push("path="+r),H.isString(o)&&i.push("domain="+o),!0===s&&i.push("secure"),document.cookie=i.join("; ")},read(e){const t=document.cookie.match(new RegExp("(^|;\\s*)("+e+")=([^;]*)"));return t?decodeURIComponent(t[3]):null},remove(e){this.write(e,"",Date.now()-864e5)}}:{write(){},read:()=>null,remove(){}};function Ue(e,t,n){let r=!/^([a-z][a-z\d+\-.]*:)?\/\//i.test(t);return e&&(r||0==n)?function(e,t){return t?e.replace(/\/?\/$/,"")+"/"+t.replace(/^\/+/,""):e}(e,t):t}const Pe=e=>e instanceof Oe?{...e}:e;function _e(e,t){t=t||{};const n={};function r(e,t,n,r){return H.isPlainObject(e)&&H.isPlainObject(t)?H.merge.call({caseless:r},e,t):H.isPlainObject(t)?H.merge({},t):H.isArray(t)?t.slice():t}function o(e,t,n,o){return H.isUndefined(t)?H.isUndefined(e)?void 0:r(void 0,e,0,o):r(e,t,0,o)}function s(e,t){if(!H.isUndefined(t))return r(void 0,t)}function i(e,t){return H.isUndefined(t)?H.isUndefined(e)?void 0:r(void 0,e):r(void 0,t)}function a(n,o,s){return s in t?r(n,o):s in e?r(void 0,n):void 0}const c={url:s,method:s,data:s,baseURL:i,transformRequest:i,transformResponse:i,paramsSerializer:i,timeout:i,timeoutMessage:i,withCredentials:i,withXSRFToken:i,adapter:i,responseType:i,xsrfCookieName:i,xsrfHeaderName:i,onUploadProgress:i,onDownloadProgress:i,decompress:i,maxContentLength:i,maxBodyLength:i,beforeRedirect:i,transport:i,httpAgent:i,httpsAgent:i,cancelToken:i,socketPath:i,responseEncoding:i,validateStatus:a,headers:(e,t,n)=>o(Pe(e),Pe(t),0,!0)};return H.forEach(Object.keys(Object.assign({},e,t)),(function(r){const s=c[r]||o,i=s(e[r],t[r],r);H.isUndefined(i)&&s!==a||(n[r]=i)})),n}const Fe=e=>{const t=_e({},e);let n,{data:r,withXSRFToken:o,xsrfHeaderName:s,xsrfCookieName:i,headers:a,auth:c}=t;if(t.headers=a=Oe.from(a),t.url=ne(Ue(t.baseURL,t.url,t.allowAbsoluteUrls),e.params,e.paramsSerializer),c&&a.set("Authorization","Basic "+btoa((c.username||"")+":"+(c.password?unescape(encodeURIComponent(c.password)):""))),H.isFormData(r))if(fe.hasStandardBrowserEnv||fe.hasStandardBrowserWebWorkerEnv)a.setContentType(void 0);else if(!1!==(n=a.getContentType())){const[e,...t]=n?n.split(";").map((e=>e.trim())).filter(Boolean):[];a.setContentType([e||"multipart/form-data",...t].join("; "))}if(fe.hasStandardBrowserEnv&&(o&&H.isFunction(o)&&(o=o(t)),o||!1!==o&&je(t.url))){const e=s&&i&&Ne.read(i);e&&a.set(s,e)}return t},Le="undefined"!=typeof XMLHttpRequest&&function(e){return new Promise((function(t,n){const r=Fe(e);let o=r.data;const s=Oe.from(r.headers).normalize();let i,a,c,l,u,{responseType:f,onUploadProgress:d,onDownloadProgress:p}=r;function h(){l&&l(),u&&u(),r.cancelToken&&r.cancelToken.unsubscribe(i),r.signal&&r.signal.removeEventListener("abort",i)}let m=new XMLHttpRequest;function y(){if(!m)return;const r=Oe.from("getAllResponseHeaders"in m&&m.getAllResponseHeaders());Ae((function(e){t(e),h()}),(function(e){n(e),h()}),{data:f&&"text"!==f&&"json"!==f?m.response:m.responseText,status:m.status,statusText:m.statusText,headers:r,config:e,request:m}),m=null}m.open(r.method.toUpperCase(),r.url,!0),m.timeout=r.timeout,"onloadend"in m?m.onloadend=y:m.onreadystatechange=function(){m&&4===m.readyState&&(0!==m.status||m.responseURL&&0===m.responseURL.indexOf("file:"))&&setTimeout(y)},m.onabort=function(){m&&(n(new J("Request aborted",J.ECONNABORTED,e,m)),m=null)},m.onerror=function(){n(new J("Network Error",J.ERR_NETWORK,e,m)),m=null},m.ontimeout=function(){let t=r.timeout?"timeout of "+r.timeout+"ms exceeded":"timeout exceeded";const o=r.transitional||oe;r.timeoutErrorMessage&&(t=r.timeoutErrorMessage),n(new J(t,o.clarifyTimeoutError?J.ETIMEDOUT:J.ECONNABORTED,e,m)),m=null},void 0===o&&s.setContentType(null),"setRequestHeader"in m&&H.forEach(s.toJSON(),(function(e,t){m.setRequestHeader(t,e)})),H.isUndefined(r.withCredentials)||(m.withCredentials=!!r.withCredentials),f&&"json"!==f&&(m.responseType=r.responseType),p&&([c,u]=ve(p,!0),m.addEventListener("progress",c)),d&&m.upload&&([a,l]=ve(d),m.upload.addEventListener("progress",a),m.upload.addEventListener("loadend",l)),(r.cancelToken||r.signal)&&(i=t=>{m&&(n(!t||t.type?new Te(null,e,m):t),m.abort(),m=null)},r.cancelToken&&r.cancelToken.subscribe(i),r.signal&&(r.signal.aborted?i():r.signal.addEventListener("abort",i)));const b=function(e){const t=/^([-+\w]{1,25})(:?\/\/|:)/.exec(e);return t&&t[1]||""}(r.url);b&&-1===fe.protocols.indexOf(b)?n(new J("Unsupported protocol "+b+":",J.ERR_BAD_REQUEST,e)):m.send(o||null)}))},Be=(e,t)=>{const{length:n}=e=e?e.filter(Boolean):[];if(t||n){let n,r=new AbortController;const o=function(e){if(!n){n=!0,i();const t=e instanceof Error?e:this.reason;r.abort(t instanceof J?t:new Te(t instanceof Error?t.message:t))}};let s=t&&setTimeout((()=>{s=null,o(new J(`timeout ${t} of ms exceeded`,J.ETIMEDOUT))}),t);const i=()=>{e&&(s&&clearTimeout(s),s=null,e.forEach((e=>{e.unsubscribe?e.unsubscribe(o):e.removeEventListener("abort",o)})),e=null)};e.forEach((e=>e.addEventListener("abort",o)));const{signal:a}=r;return a.unsubscribe=()=>H.asap(i),a}},ke=function*(e,t){let n=e.byteLength;if(!t||n{const o=async function*(e,t){for await(const n of De(e))yield*ke(n,t)}(e,t);let s,i=0,a=e=>{s||(s=!0,r&&r(e))};return new ReadableStream({async pull(e){try{const{done:t,value:r}=await o.next();if(t)return a(),void e.close();let s=r.byteLength;if(n){let e=i+=s;n(e)}e.enqueue(new Uint8Array(r))}catch(e){throw a(e),e}},cancel:e=>(a(e),o.return())},{highWaterMark:2})},Ie="function"==typeof fetch&&"function"==typeof Request&&"function"==typeof Response,Me=Ie&&"function"==typeof ReadableStream,ze=Ie&&("function"==typeof TextEncoder?(He=new TextEncoder,e=>He.encode(e)):async e=>new Uint8Array(await new Response(e).arrayBuffer()));var He;const Je=(e,...t)=>{try{return!!e(...t)}catch(e){return!1}},We=Me&&Je((()=>{let e=!1;const t=new Request(fe.origin,{body:new ReadableStream,method:"POST",get duplex(){return e=!0,"half"}}).headers.has("Content-Type");return e&&!t})),Ke=Me&&Je((()=>H.isReadableStream(new Response("").body))),Ve={stream:Ke&&(e=>e.body)};var $e;Ie&&($e=new Response,["text","arrayBuffer","blob","formData","stream"].forEach((e=>{!Ve[e]&&(Ve[e]=H.isFunction($e[e])?t=>t[e]():(t,n)=>{throw new J(`Response type '${e}' is not supported`,J.ERR_NOT_SUPPORT,n)})})));const Xe=async(e,t)=>{const n=H.toFiniteNumber(e.getContentLength());return null==n?(async e=>{if(null==e)return 0;if(H.isBlob(e))return e.size;if(H.isSpecCompliantForm(e)){const t=new Request(fe.origin,{method:"POST",body:e});return(await t.arrayBuffer()).byteLength}return H.isArrayBufferView(e)||H.isArrayBuffer(e)?e.byteLength:(H.isURLSearchParams(e)&&(e+=""),H.isString(e)?(await ze(e)).byteLength:void 0)})(t):n},Ge={http:null,xhr:Le,fetch:Ie&&(async e=>{let{url:t,method:n,data:r,signal:o,cancelToken:s,timeout:i,onDownloadProgress:a,onUploadProgress:c,responseType:l,headers:u,withCredentials:f="same-origin",fetchOptions:d}=Fe(e);l=l?(l+"").toLowerCase():"text";let p,h=Be([o,s&&s.toAbortSignal()],i);const m=h&&h.unsubscribe&&(()=>{h.unsubscribe()});let y;try{if(c&&We&&"get"!==n&&"head"!==n&&0!==(y=await Xe(u,r))){let e,n=new Request(t,{method:"POST",body:r,duplex:"half"});if(H.isFormData(r)&&(e=n.headers.get("content-type"))&&u.setContentType(e),n.body){const[e,t]=xe(y,ve(Ce(c)));r=qe(n.body,65536,e,t)}}H.isString(f)||(f=f?"include":"omit");const o="credentials"in Request.prototype;p=new Request(t,{...d,signal:h,method:n.toUpperCase(),headers:u.normalize().toJSON(),body:r,duplex:"half",credentials:o?f:void 0});let s=await fetch(p,d);const i=Ke&&("stream"===l||"response"===l);if(Ke&&(a||i&&m)){const e={};["status","statusText","headers"].forEach((t=>{e[t]=s[t]}));const t=H.toFiniteNumber(s.headers.get("content-length")),[n,r]=a&&xe(t,ve(Ce(a),!0))||[];s=new Response(qe(s.body,65536,n,(()=>{r&&r(),m&&m()})),e)}l=l||"text";let b=await Ve[H.findKey(Ve,l)||"text"](s,e);return!i&&m&&m(),await new Promise(((t,n)=>{Ae(t,n,{data:b,headers:Oe.from(s.headers),status:s.status,statusText:s.statusText,config:e,request:p})}))}catch(t){if(m&&m(),t&&"TypeError"===t.name&&/Load failed|fetch/i.test(t.message))throw Object.assign(new J("Network Error",J.ERR_NETWORK,e,p),{cause:t.cause||t});throw J.from(t,t&&t.code,e,p)}})};H.forEach(Ge,((e,t)=>{if(e){try{Object.defineProperty(e,"name",{value:t})}catch(e){}Object.defineProperty(e,"adapterName",{value:t})}}));const Qe=e=>`- ${e}`,Ze=e=>H.isFunction(e)||null===e||!1===e,Ye=e=>{e=H.isArray(e)?e:[e];const{length:t}=e;let n,r;const o={};for(let s=0;s`adapter ${e} `+(!1===t?"is not supported by the environment":"is not available in the build")));throw new J("There is no suitable adapter to dispatch the request "+(t?e.length>1?"since :\n"+e.map(Qe).join("\n"):" "+Qe(e[0]):"as no adapter specified"),"ERR_NOT_SUPPORT")}return r};function et(e){if(e.cancelToken&&e.cancelToken.throwIfRequested(),e.signal&&e.signal.aborted)throw new Te(null,e)}function tt(e){et(e),e.headers=Oe.from(e.headers),e.data=Re.call(e,e.transformRequest),-1!==["post","put","patch"].indexOf(e.method)&&e.headers.setContentType("application/x-www-form-urlencoded",!1);return Ye(e.adapter||he.adapter)(e).then((function(t){return et(e),t.data=Re.call(e,e.transformResponse,t),t.headers=Oe.from(t.headers),t}),(function(t){return Se(t)||(et(e),t&&t.response&&(t.response.data=Re.call(e,e.transformResponse,t.response),t.response.headers=Oe.from(t.response.headers))),Promise.reject(t)}))}const nt={};["object","boolean","number","function","string","symbol"].forEach(((e,t)=>{nt[e]=function(n){return typeof n===e||"a"+(t<1?"n ":" ")+e}}));const rt={};nt.transitional=function(e,t,n){function r(e,t){return"[Axios v1.10.0] Transitional option '"+e+"'"+t+(n?". "+n:"")}return(n,o,s)=>{if(!1===e)throw new J(r(o," has been removed"+(t?" in "+t:"")),J.ERR_DEPRECATED);return t&&!rt[o]&&(rt[o]=!0,console.warn(r(o," has been deprecated since v"+t+" and will be removed in the near future"))),!e||e(n,o,s)}},nt.spelling=function(e){return(t,n)=>(console.warn(`${n} is likely a misspelling of ${e}`),!0)};const ot={assertOptions:function(e,t,n){if("object"!=typeof e)throw new J("options must be an object",J.ERR_BAD_OPTION_VALUE);const r=Object.keys(e);let o=r.length;for(;o-- >0;){const s=r[o],i=t[s];if(i){const t=e[s],n=void 0===t||i(t,s,e);if(!0!==n)throw new J("option "+s+" must be "+n,J.ERR_BAD_OPTION_VALUE)}else if(!0!==n)throw new J("Unknown option "+s,J.ERR_BAD_OPTION)}},validators:nt},st=ot.validators;class it{constructor(e){this.defaults=e||{},this.interceptors={request:new re,response:new re}}async request(e,t){try{return await this._request(e,t)}catch(e){if(e instanceof Error){let t={};Error.captureStackTrace?Error.captureStackTrace(t):t=new Error;const n=t.stack?t.stack.replace(/^.+\n/,""):"";try{e.stack?n&&!String(e.stack).endsWith(n.replace(/^.+\n.+\n/,""))&&(e.stack+="\n"+n):e.stack=n}catch(e){}}throw e}}_request(e,t){"string"==typeof e?(t=t||{}).url=e:t=e||{},t=_e(this.defaults,t);const{transitional:n,paramsSerializer:r,headers:o}=t;void 0!==n&&ot.assertOptions(n,{silentJSONParsing:st.transitional(st.boolean),forcedJSONParsing:st.transitional(st.boolean),clarifyTimeoutError:st.transitional(st.boolean)},!1),null!=r&&(H.isFunction(r)?t.paramsSerializer={serialize:r}:ot.assertOptions(r,{encode:st.function,serialize:st.function},!0)),void 0!==t.allowAbsoluteUrls||(void 0!==this.defaults.allowAbsoluteUrls?t.allowAbsoluteUrls=this.defaults.allowAbsoluteUrls:t.allowAbsoluteUrls=!0),ot.assertOptions(t,{baseUrl:st.spelling("baseURL"),withXsrfToken:st.spelling("withXSRFToken")},!0),t.method=(t.method||this.defaults.method||"get").toLowerCase();let s=o&&H.merge(o.common,o[t.method]);o&&H.forEach(["delete","get","head","post","put","patch","common"],(e=>{delete o[e]})),t.headers=Oe.concat(s,o);const i=[];let a=!0;this.interceptors.request.forEach((function(e){"function"==typeof e.runWhen&&!1===e.runWhen(t)||(a=a&&e.synchronous,i.unshift(e.fulfilled,e.rejected))}));const c=[];let l;this.interceptors.response.forEach((function(e){c.push(e.fulfilled,e.rejected)}));let u,f=0;if(!a){const e=[tt.bind(this),void 0];for(e.unshift.apply(e,i),e.push.apply(e,c),u=e.length,l=Promise.resolve(t);f{if(!n._listeners)return;let t=n._listeners.length;for(;t-- >0;)n._listeners[t](e);n._listeners=null})),this.promise.then=e=>{let t;const r=new Promise((e=>{n.subscribe(e),t=e})).then(e);return r.cancel=function(){n.unsubscribe(t)},r},e((function(e,r,o){n.reason||(n.reason=new Te(e,r,o),t(n.reason))}))}throwIfRequested(){if(this.reason)throw this.reason}subscribe(e){this.reason?e(this.reason):this._listeners?this._listeners.push(e):this._listeners=[e]}unsubscribe(e){if(!this._listeners)return;const t=this._listeners.indexOf(e);-1!==t&&this._listeners.splice(t,1)}toAbortSignal(){const e=new AbortController,t=t=>{e.abort(t)};return this.subscribe(t),e.signal.unsubscribe=()=>this.unsubscribe(t),e.signal}static source(){let e;return{token:new ct((function(t){e=t})),cancel:e}}}const lt=ct;const ut={Continue:100,SwitchingProtocols:101,Processing:102,EarlyHints:103,Ok:200,Created:201,Accepted:202,NonAuthoritativeInformation:203,NoContent:204,ResetContent:205,PartialContent:206,MultiStatus:207,AlreadyReported:208,ImUsed:226,MultipleChoices:300,MovedPermanently:301,Found:302,SeeOther:303,NotModified:304,UseProxy:305,Unused:306,TemporaryRedirect:307,PermanentRedirect:308,BadRequest:400,Unauthorized:401,PaymentRequired:402,Forbidden:403,NotFound:404,MethodNotAllowed:405,NotAcceptable:406,ProxyAuthenticationRequired:407,RequestTimeout:408,Conflict:409,Gone:410,LengthRequired:411,PreconditionFailed:412,PayloadTooLarge:413,UriTooLong:414,UnsupportedMediaType:415,RangeNotSatisfiable:416,ExpectationFailed:417,ImATeapot:418,MisdirectedRequest:421,UnprocessableEntity:422,Locked:423,FailedDependency:424,TooEarly:425,UpgradeRequired:426,PreconditionRequired:428,TooManyRequests:429,RequestHeaderFieldsTooLarge:431,UnavailableForLegalReasons:451,InternalServerError:500,NotImplemented:501,BadGateway:502,ServiceUnavailable:503,GatewayTimeout:504,HttpVersionNotSupported:505,VariantAlsoNegotiates:506,InsufficientStorage:507,LoopDetected:508,NotExtended:510,NetworkAuthenticationRequired:511};Object.entries(ut).forEach((([e,t])=>{ut[t]=e}));const ft=ut;const dt=function t(n){const r=new at(n),o=e(at.prototype.request,r);return H.extend(o,at.prototype,r,{allOwnKeys:!0}),H.extend(o,r,null,{allOwnKeys:!0}),o.create=function(e){return t(_e(n,e))},o}(he);dt.Axios=at,dt.CanceledError=Te,dt.CancelToken=lt,dt.isCancel=Se,dt.VERSION="1.10.0",dt.toFormData=Q,dt.AxiosError=J,dt.Cancel=dt.CanceledError,dt.all=function(e){return Promise.all(e)},dt.spread=function(e){return function(t){return e.apply(null,t)}},dt.isAxiosError=function(e){return H.isObject(e)&&!0===e.isAxiosError},dt.mergeConfig=_e,dt.AxiosHeaders=Oe,dt.formToJSON=e=>de(H.isHTMLForm(e)?new FormData(e):e),dt.getAdapter=Ye,dt.HttpStatusCode=ft,dt.default=dt;const pt=dt,{Axios:ht,AxiosError:mt,CanceledError:yt,isCancel:bt,CancelToken:gt,VERSION:wt,all:Et,Cancel:Ot,isAxiosError:Rt,spread:St,toFormData:Tt,AxiosHeaders:At,HttpStatusCode:vt,formToJSON:xt,getAdapter:Ct,mergeConfig:jt}=pt;export{ht as Axios,mt as AxiosError,At as AxiosHeaders,Ot as Cancel,gt as CancelToken,yt as CanceledError,vt as HttpStatusCode,wt as VERSION,Et as all,pt as default,xt as formToJSON,Ct as getAdapter,Rt as isAxiosError,bt as isCancel,jt as mergeConfig,St as spread,Tt as toFormData}; +//# sourceMappingURL=axios.min.js.map diff --git a/ui/vhtml/utils.js b/ui/vhtml/utils.js new file mode 100644 index 0000000..6847e2d --- /dev/null +++ b/ui/vhtml/utils.js @@ -0,0 +1,293 @@ + + +function CamelToKebabCase(str) { + // 首先将字符串的第一个字符转换为小写,避免在首字符前加上'-' + if (str.length === 0) return ''; + let firstChar = str.charAt(0).toLowerCase(); + + // 对剩余部分应用原逻辑:找到每个大写字母,并替换为连字符加上该字母的小写形式 + let rest = str.slice(1).replace(/([A-Z])/g, function(match, p1) { + return '-' + p1.toLowerCase(); + }); + + return firstChar + rest; +} + +const outerClickList = [] +const globalClick = document.addEventListener('click', (event) => { + outerClickList.forEach((item) => { + if (item?.dom instanceof Element && typeof item?.callback === 'function') { + if (!item.dom.contains(event.target)) { + item.callback(event) + } + } + }) +}) +const AddClicker = (dom, typ, callback) => { + if (typ === 'outer') { + let idx = outerClickList.length + outerClickList.push({ dom, callback }) + return () => { + outerClickList[idx] = null + } + } +} + +const EventsList = [ + // 窗口和框架事件 + 'load', + 'unload', + 'beforeunload', + 'resize', + 'scroll', + + // 表单事件 + 'submit', + 'reset', + 'input', + 'change', + 'focus', + 'blur', + + // 键盘事件 + 'keydown', + 'keypress', + 'keyup', + + // 鼠标事件 + 'click', + 'dblclick', + 'contextmenu', + 'mousedown', + 'mouseup', + 'mousemove', + 'mouseover', + 'mouseout', + 'mouseenter', + 'mouseleave', + + // 触摸事件 + 'touchstart', + 'touchmove', + 'touchend', + 'touchcancel', + + // 拖拽事件 + 'drag', + 'dragstart', + 'dragend', + 'dragover', + 'dragenter', + 'dragleave', + 'drop', + + // 剪贴板事件 + 'copy', + 'cut', + 'paste', + + // 动画事件 + 'animationstart', + 'animationend', + 'animationiteration', + + // 过渡事件 + 'transitionend', + + // 文件操作事件 + 'abort', + 'error', + 'loadstart', + 'progress', + + // 音视频事件 + 'play', + 'pause', + 'ended', + 'volumechange', + 'timeupdate', + 'loadeddata', + 'waiting', + 'playing', + + // 网络状态事件 + 'online', + 'offline', + + // 存储事件 + 'storage', + + // 页面可见性事件 + 'visibilitychange' +]; + +function BindInputDomValue(dom, data, key, watch) { + const element = typeof dom === 'string' ? document.querySelector(dom) : dom; + + if (!element) { + console.error('DOM元素未找到'); + return; + } + // 根据元素类型进行双向绑定 + const elementType = element.type || element.tagName.toLowerCase(); + switch (elementType) { + // 文本输入类 + case 'text': + case 'password': + case 'email': + case 'tel': + case 'url': + case 'search': + case 'number': + case 'range': + case 'color': + case 'date': + case 'time': + case 'datetime-local': + case 'month': + case 'week': + case 'hidden': + case 'textarea': + watch(() => data[key], (value) => { + if (value === undefined) { + element.value = '' + } else { + element.value = value + } + }) + element.addEventListener('input', function() { + data[key] = this.value; + }); + break; + case 'checkbox': + watch(function() { + element.checked = !!data[key]; + }); + element.addEventListener('change', function() { + data[key] = this.checked; + console.log(data, data[key]) + }); + break; + // 单选框 + case 'radio': + // 初始化 + watch(() => { + element.checked = element.value === data[key]; + }) + element.addEventListener('change', function() { + if (this.checked) { + data[key] = this.value; + } + }); + break; + + // 下拉选择框 + case 'select-one': + case 'select-multiple': + watch(() => { + let newValue = data[key] + if (element.multiple) { + const values = Array.isArray(newValue) ? newValue : []; + for (let i = 0; i < element.options.length; i++) { + element.options[i].selected = values.includes(element.options[i].value); + } + } else { + element.value = newValue || ''; + } + }); + // 监听变化 + element.addEventListener('change', function() { + if (this.multiple) { + // 多选 + const selectedValues = []; + for (let i = 0; i < this.options.length; i++) { + if (this.options[i].selected) { + selectedValues.push(this.options[i].value); + } + } + data[key] = selectedValues; + } else { + // 单选 + data[key] = this.value; + } + }); + break; + + default: + console.warn(`${elementType} not support v!bind only for input element`, element); + return false + } + return true +} + +function SetAttr(dom, key, value) { + // 属性名映射表 + const propertyMap = { + 'htmlfor': 'htmlFor', + 'readonly': 'readOnly', + 'maxlength': 'maxLength', + 'minlength': 'minLength', + 'cellspacing': 'cellSpacing', + 'cellpadding': 'cellPadding', + 'rowspan': 'rowSpan', + 'colspan': 'colSpan', + 'tabindex': 'tabIndex', + 'usemap': 'useMap', + 'frameborder': 'frameBorder', + 'contenteditable': 'contentEditable', + 'spellcheck': 'spellcheck', + 'innerhtml': 'innerHTML', + 'innertext': 'innerText', + 'autocapitalize': 'autocapitalize', + }; + + // 需要使用 DOM 属性设置的属性 + const domProperties = new Set([ + 'innerHTML', 'innerText', 'outerHTML', 'textContent', + 'value', 'checked', 'selected', 'disabled', 'readOnly', + 'maxLength', 'minLength', 'htmlFor', + 'tabIndex', 'scrollTop', 'scrollLeft', 'scrollWidth', 'scrollHeight', + 'clientWidth', 'clientHeight', 'offsetWidth', 'offsetHeight', + 'style', 'dataset' + ]); + + // 布尔属性 + const booleanAttributes = new Set([ + 'checked', 'selected', 'disabled', 'readonly', 'required', + 'hidden', 'autofocus', 'multiple', 'novalidate' + ]); + + // 转换属性名 + const lowerKey = key.toLowerCase(); + const mappedKey = propertyMap[lowerKey] || key; + + + + // 设置属性的策略: + if (domProperties.has(mappedKey)) { + // DOM 属性 + if (value === undefined) { + dom[mappedKey] = '' + } else { + dom[mappedKey] = value; + } + } else if (booleanAttributes.has(lowerKey)) { + // 布尔属性 + if (value) { + dom.setAttribute(lowerKey, ''); + } else { + dom.removeAttribute(lowerKey); + } + } else { + // 其他属性使用 setAttribute + if (value === undefined) { + dom.removeAttribute(key); + } else { + dom.setAttribute(key, value); + } + } +} + + +export default { CamelToKebabCase, EventsList, BindInputDomValue, SetAttr, AddClicker } + diff --git a/ui/vhtml/v.js b/ui/vhtml/v.js new file mode 100644 index 0000000..caf4ebe --- /dev/null +++ b/ui/vhtml/v.js @@ -0,0 +1,1128 @@ +/* + * v.js + * Copyright (C) 2024 veypi + * + * Distributed under terms of the GPL license. + */ +import vproxy from './vproxy.js' +import vget from './vget.js' +import vrouter from './vrouter.js' +import utils from './utils.js' +import setupVdev from './vdev.js' + +(async function() { + + const globalStyle = document.createElement('style') + globalStyle.innerHTML = ` + [vref] { + display: block; + } + [vparsing] { + display: none; + -webkit-text-fill-color: transparent; + } + vslot, vrouter { + display: block; + } +` + if (document.head.firstChild) { + document.head.insertBefore(globalStyle, document.head.firstChild) + } else { + document.head.appendChild(globalStyle) + } + const DelayCache = [] + const config = { attributes: false, childList: true, subtree: true, characterData: false } + const runVdelay = (d) => { + if (!d.isConnected) { + return + } + let delay = d.getAttribute('vdelay') + if (delay) { + let fc = DelayCache[delay] + if (fc) { + fc(d) + } else { + console.error('delay not found:', delay, d) + } + } + } + const callback = function(mutationsList, observer) { + mutationsList.forEach(function(mutation) { + for (let node of mutation.addedNodes) { + if (node.nodeType === 1) { // 元素节点 + runVdelay(node) + node.querySelectorAll('*[vdelay]').forEach(runVdelay) + } + } + }) + } + const observer = new MutationObserver(callback); + observer.observe(document.body, config); + + function recordGet(code, data) { + code = `with (sandbox) { ${code} }` + const fn = new Function('sandbox', code); + let res = vproxy.Wrap({}) + let keys = [] + const proxy = new Proxy(data, { + // 拦截所有属性,防止到 Proxy 对象以外的作用域链查找。 + has(target, key) { + return true; + }, + get(target, key, receiver) { + if (key === Symbol.unscopables) { + return undefined; + } + let v = Reflect.get(target, key, receiver); + if (keys.indexOf(key) === -1) { + keys.push(key) + } + return v + }, + set(target, key, newValue, receiver) { + return false + } + }); + fn(proxy) + vproxy.Watch(() => { + keys.forEach(k => { + if (res[k] !== data[k]) { + res[k] = data[k] + } + }) + }) + return res + } + + function findLastAccess(code, data) { + code = `with (sandbox) { ${code} }` + const fn = new Function('sandbox', code); + let res = { + data: null, + key: null, + } + const wrap = (tmp) => { + return new Proxy(tmp, { + // 拦截所有属性,防止到 Proxy 对象以外的作用域链查找。 + has(target, key) { + return true; + }, + get(target, key, receiver) { + if (key === Symbol.unscopables) { + return undefined; + } + let v = Reflect.get(target, key, receiver); + res.data = target + res.key = key + if (typeof v === 'function') { + console.warn('vhtml not support function with "v:" variables bind') + } + if (typeof v === 'object' && v) { + return wrap(v) + } + return v + }, + set(target, key, newValue, receiver) { + // console.log('set', target, key, newValue) + // return Reflect.set(target, key, newValue, receiver); + return false + } + }) + } + fn(wrap(data)) + return res + } + + const varRegex = /{{|}}/g; + const vforRegex = /^(\s*(\w+)\s+in\s+|\((\w+),\s*(\w+)\)\s+in\s+)([\w\?\$\.\[\]\(\)'"]+)$/ + class vhtml { + /** @type {HTMLElement} */ + app = null + scoped = null + vget = vget + vproxy = vproxy + __noproxy = true + $router = vrouter.$router + constructor(id) { + if (typeof id === 'string') { + this.app = document.getElementById(id) + } else if (id instanceof HTMLElement) { + this.app = id + } else { + this.app = document.body + } + if (!this.app) { + console.error(`Can't find element by id: ${id}`) + return + } + let init = async () => { + // vget.SetBaseFile(await vget.FetchFile(window.location.pathname)) + let mainParser = await vget.FetchUI(window.location.pathname, {}, true) + this.scoped = mainParser.env?.scoped || '' + if (mainParser.env?.vdev && window.self !== window.top) { + setupVdev() + } + this.parseRef('root', this.app, {}, mainParser.env || {}, mainParser, true) + } + init() + } + /** + * @param{HTMLElement} dom + * @param {Object} scopedData + * */ + async parseDom(dom, scopedData = {}, env) { + if (env instanceof HTMLElement) { + console.log(env) + throw new Error('env error') + } + let nodeName = dom.nodeName.toLowerCase() + if (dom.nodeType === 3) { + this.parseTextNode(dom, scopedData, env) + return + } else if (dom.nodeType === 8) { + // comment node + return + } else if (dom.nodeType !== 1) { + console.log('Other Node Type:', dom.nodeType, dom); + return + } + if (dom.hasAttribute('no-vhtml') || dom.vparsed) { + return + } + + let vfortxt = dom.getAttribute('v-for') + if (vfortxt !== null) { + this.parseVfor(vfortxt, dom, scopedData, env) + return + } + if (nodeName.indexOf('-') !== -1) { + let url = '/' + nodeName.split('-').join('/') + let singleMode = dom.hasAttribute('single') + this.parseRef(url, dom, scopedData, env, null, singleMode) + dom.vparsed = true + return + } + if (dom.getAttribute(':vsrc')) { + let code = dom.getAttribute(':vsrc') + dom.removeAttribute(':vsrc') + let attrs = Array.from(dom.attributes).map(a => { + let res = { name: a.name, value: a.value } + return res + }) + let oldChilds = Array.from(dom.childNodes) + vproxy.Watch(() => { + delete dom.vparsed + dom.setAttribute('vparsing', '') + let vsrc = vproxy.Run(code, scopedData, env) + if (!vsrc) { + return + } + Array.from(dom.attributes).forEach(a => { dom.removeAttribute(a.name) }) + dom.innerHTML = '' + attrs.forEach(a => { dom.setAttribute(a.name, a.value) }) + oldChilds.forEach(c => { dom.appendChild(c.cloneNode(true)) }) + this.parseRef(vsrc, dom, scopedData, env, null, false) + dom.vparsed = true + }) + return + } + if (dom.getAttribute('vsrc')) { + let singleMode = dom.hasAttribute('single') + this.parseRef(dom.getAttribute('vsrc'), dom, scopedData, env, null, singleMode) + dom.vparsed = true + return + } + if (nodeName === 'div' && dom.getAttribute('v-html')) { + let vhtmlCode = dom.getAttribute('v-html') + dom.removeAttribute('v-html') + dom.innerHTML = '' + this.parseAttrs(dom, scopedData, env) + dom.vparsed = true + vproxy.Watch(() => { + let innerHTML = vproxy.Run(vhtmlCode, scopedData, env) + dom.innerHTML = innerHTML + let childs = this.parseVif(Array.from(dom.childNodes), scopedData, env) + for (let n of childs) { + this.parseDom(n, scopedData, env) + } + }) + return + } + if (nodeName === 'vslot') { + this.parseSlots(dom, scopedData, env) + dom.vparsed = true + return + } + if (nodeName === 'vrouter') { + this.parseAttrs(dom, scopedData, env) + vrouter.$router.ParseVrouter(this, dom, env) + return + } + this.parseAttrs(dom, scopedData, env) + let childs = this.parseVif(Array.from(dom.childNodes), scopedData, env) + for (let n of childs) { + this.parseDom(n, scopedData, env) + } + dom.vparsed = true + } + + onMountedRun(dom, cb, once = true) { + if (once) { + if (dom.isConnected) { + cb(dom) + return + } + let did = DelayCache.push((dom) => { + dom.removeAttribute('vdelay') + cb(dom) + }) + dom.setAttribute('vdelay', did - 1) + return + } + if (dom.isConnected) { + cb(dom) + } + let did = DelayCache.push(cb) + dom.setAttribute('vdelay', did - 1) + } + + /** + * @param{string} name + * @param{HTMLElement} dom + * */ + AllENVs = {} + async parseRef(vsrc, dom, data, env, target, singleMode = false) { + dom.setAttribute('vparsing', '') + let oldEnv = env + let vrefof = dom.getAttribute('vrefof') + let parentRef = dom.closest(`*[vref='${vrefof}']`) + if (parentRef) { + env = parentRef.$env + } else { + // console.log('parentRef not found:', vrefof,vsrc) + } + if (!target && vsrc) { + if (!vsrc.endsWith('.html')) { + vsrc = vsrc + '.html' + } + target = await vget.FetchUI(vsrc, env, dom.hasAttribute('scoped')) + } + env = Object.assign({}, env, target?.env || {}) + // env = target.env + dom.$env = env + dom.$vsrc = vsrc + env.$router = vrouter.$router + env.$emit = (evt, ...args) => { + evt = evt.toLowerCase() + if (!dom.$vevent) { + return + } + let fc = dom.$vevent[evt] + if (fc && typeof fc === 'function') { + fc(...args) + } + } + let originData = await this.setupRef(dom, data, oldEnv, target, singleMode) + + if (singleMode) { + this.parseAttrs(dom, originData, env, target?.customAttrs) + } else { + this.parseAttrs(dom, data, oldEnv, target?.customAttrs) + } + let childs = this.parseVif(Array.from(dom.childNodes), originData, env) + for (let n of childs) { + this.parseDom(n, originData, env) + } + dom.removeAttribute('vparsing') + this.mountRef(dom, originData, env, target) + } + + /** + * @param {HTMLElement} dom + * @parm {Object} data + * @param {{heads:HTMLElement[],body:HTMLElement,scripts:HTMLElement[],setup:HTMLElement}} target + * */ + async setupRef(dom, data, env, target, singleMode = false) { + let originData = vproxy.Wrap({}) + if (target.setup) { + let s = target.setup.innerHTML + s = await vproxy.ParseImport(s, originData, dom.$env, dom.$vsrc) + await vproxy.AsyncRun(s, originData, dom.$env, { + $node: dom + }) + } + dom.$refScope = data + dom.$refData = originData + if (singleMode) { + return originData + } + if (!dom.$refSlots) { + // dom 预定义好内容 + let slots = vproxy.Wrap({}) + dom.childNodes.forEach((n) => { + let nName = n.getAttribute ? n.getAttribute('vslot') : '' + nName = nName || '' + if (!slots[nName]) { + slots[nName] = [] + } + slots[nName].push(n) + }) + dom.$refSlots = slots + } + dom.innerHTML = '' + let now = target.body.cloneNode(true) + dom.append(...now.childNodes) + + // 处理调用方attr 传参 + Object.keys(originData).forEach(k => { + const localK = utils.CamelToKebabCase(k) + if (typeof originData[k] === 'boolean') { + if (dom.hasAttribute(k) || dom.hasAttribute(localK)) { + originData[k] = true + } + } else if (dom.hasAttribute(k)) { + originData[k] = dom.getAttribute(k) + dom.removeAttribute(k) + } else if (dom.hasAttribute(localK)) { + originData[k] = dom.getAttribute(localK) + dom.removeAttribute(localK) + } + if (dom.hasAttribute(':' + k) || dom.hasAttribute(':' + localK)) { + let val = dom.getAttribute(':' + k) || dom.getAttribute(':' + localK) + dom.removeAttribute(':' + k) + dom.removeAttribute(':' + localK) + // 此时数据还没有监听,删除旧对象,使得外部的对象直接绑定在内部$data上 + delete originData[k] + if (val) { + vproxy.Watch(() => vproxy.Run(val, data, env), () => { + originData[k] = vproxy.Run(val, data, env) + }, { deep: true }) + } else { + vproxy.Watch(() => data[k], () => { + originData[k] = data[k] + }, { deep: true }) + } + } + if (dom.hasAttribute('v:' + k) || dom.hasAttribute('v:' + localK)) { + let val = dom.getAttribute('v:' + k) || dom.getAttribute('v:' + localK) + dom.removeAttribute('v:' + k) + dom.removeAttribute('v:' + localK) + if (!val) { + val = k + } + delete originData[k] + vproxy.Watch(() => findLastAccess(val, data), (args) => { + if (args && args.data && args.key) { + originData[k] = args.data[args.key] + } else { + console.warn('not found variables in:' + val) + } + }) + vproxy.Watch(() => originData[k], () => { + let args = findLastAccess(val, data) + if (args && args.data && args.key) { + args.data[args.key] = originData[k] + } else { + console.warn('not found variables in:' + val) + } + }) + } + }) + + // handle local component attr + let attrs = Array.from(now.attributes) + attrs = attrs.filter(a => { + if (this.parseAttr(dom, a.name, a.value, originData, env)) { + now.removeAttribute(a.name) + return false + } + return true + }) + attrs.forEach((a) => { + if (a.name === 'class') { + dom.classList.add(...a.value.trim().split(/\s+/)) + } else if (a.name === 'style') { + let styles = a.value.split(';') + for (let s of styles) { + let ss = s.split(':') + if (ss.length === 2 && !dom.style[ss[0]]) { + let skey = ss[0].trim() + if (skey.startsWith('--')) { + dom.style.setProperty(skey, ss[1].trim()) + } else { + dom.style[skey] = ss[1].trim() + } + } + } + } else if (!dom.getAttribute(a.name)) { + dom.setAttribute(a.name, a.value) + } + }) + return originData + } + + async mountRef(dom, scopedData, env, target) { + for (let s of target.scripts) { + if (s.hasAttribute('active')) { + this.onMountedRun(dom, () => { + vproxy.AsyncRun(s.innerHTML, scopedData, env, { $node: dom, $watch: vproxy.Watch }) + }, false) + } else { + vproxy.AsyncRun(s.innerHTML, scopedData, env, { $node: dom, $watch: vproxy.Watch }) + } + } + } + + parseAttrs(dom, data, env, attrs) { + if (dom.nodeName === 'A') { + this.parseAHref(dom, data, env) + } + Array.from(dom.attributes).forEach(a => { + if (this.parseAttr(dom, a.name, a.value, data, env)) { + dom.removeAttribute(a.name) + } + }) + if (attrs) { + // just for body element + Object.keys(attrs).forEach(k => { + this.parseAttr(dom, k, attrs[k], dom.$refData, env) + }) + } + if (dom.hasAttribute('v-show')) { + let code = dom.getAttribute('v-show') + let oldDisplay = dom.style.display + vproxy.Watch(() => { + let res = vproxy.Run(code, data, env) + if (res) { + dom.style.display = oldDisplay + } else { + dom.style.display = 'none' + } + }) + } + } + + parseAHref(dom, data, env) { + if (!dom.hasAttribute("href") && !dom.hasAttribute(":href")) { + return + } + if (dom.hasAttribute(":href")) { + let code = dom.getAttribute(":href") + dom.removeAttribute(":href") + vproxy.Watch(() => { + let href = vproxy.Run(code, data, env) + console.log(code, href, env) + if (!href || href.startsWith('#') || href.startsWith('http')) { + return + } else if (href.startsWith('@')) { + dom.setAttribute('href', href.slice(1)) + } else if (href) { + let scoped = env?.scoped + if (scoped) { + href = scoped + href + } + dom.setAttribute('href', href) + } + }) + } + const fc = (to) => { + let url = to?.fullPath + if (dom.getAttribute('href') === url) { + dom.setAttribute('active', '') + } else { + dom.removeAttribute('active') + } + } + fc(vrouter.$router.current) + vrouter.$router.onChange(fc) + } + + /** + * @param {HTMLElement} dom + * */ + parseAttr(dom, name, value, data, env) { + if (name.startsWith(':')) { + let attrName = name.slice(1) + if (attrName === 'class' || attrName === 'style') { + this.handleStyle(dom, attrName, value, data, env) + } else { + vproxy.Watch(() => { + let res + if (value) { + res = vproxy.Run(value, data, env) + } else { + res = data[attrName] + } + utils.SetAttr(dom, attrName, res) + }) + } + return true + } else if (name.startsWith('@')) { + this.handleEvent(dom, name, value, data, env) + return true + } else if (name.indexOf('!') > -1) { + console.warn('! prefix is deprecated, use : instead:', name, value, dom) + } else if (name.startsWith('v:')) { + let args = findLastAccess(value, data) + if (args && args.data && args.key) { + let vkey = args.key + let vdata = args.data + return utils.BindInputDomValue(dom, vdata, vkey, vproxy.Watch) + } else { + console.warn('not found variables in:' + value) + } + } else if (name === 'vdom') { + let vbind = findLastAccess(value, data) + if (vbind && vbind.data && vbind.key) { + vbind.data[vbind.key] = dom + } else { + console.warn('not found variables in:' + value) + } + return true + } + return false + } + handleStyle(dom, attrName, value, data, env) { + let oldValue = '' + vproxy.Watch(() => { + let res = vproxy.Run(value, data, env) + if (typeof res === 'function') { + res = res() + } + if (attrName === 'class') { + if (oldValue) { + dom.classList.remove(...oldValue.split(/\s+/)) + oldValue = '' + } + if (res instanceof Array) { + oldValue = '' + res.forEach(r => { + if (typeof r === 'string' && r.length) { + oldValue += ' ' + r + } else if (typeof r === 'object') { + for (let k in r) { + if (r[k]) { + oldValue += ' ' + k + } + } + } + }) + } else if (typeof res === 'string' && res.length) { + oldValue = res.trim() + } else if (typeof res === 'object') { + oldValue = '' + for (let k in res) { + if (res[k]) { + oldValue += ' ' + k + } + } + } else if (res) { + console.warn('class value error:', res) + } + oldValue = oldValue.trim() + if (oldValue) { + dom.classList.add(...oldValue.split(/\s+/)) + } + } else if (attrName === 'style') { + if (oldValue) { + if (typeof oldValue === 'object') { + for (let k in oldValue) { + if (k.startsWith('--')) { + dom.style.removeProperty(k) + } else { + dom.style[k] = '' + } + } + } else if (typeof oldValue === 'string') { + let styles = oldValue.split(';') + for (let s of styles) { + let ss = s.split(':') + if (ss.length === 2) { + if (ss[0].trim().startsWith('--')) { + dom.style.removeProperty(ss[0].trim()) + } else { + dom.style[ss[0].trim()] = '' + } + } + } + } + } + if (typeof res === 'object') { + for (let k in res) { + if (k.startsWith('--')) { + dom.style.setProperty(k, res[k]) + } else { + dom.style[k] = res[k] + } + } + } else if (typeof res === 'string') { + let styles = res.split(';') + for (let s of styles) { + let ss = s.split(':') + if (ss.length === 2) { + if (ss[0].trim().startsWith('--')) { + dom.style.setProperty(ss[0].trim(), ss[1].trim()) + } else { + dom.style[ss[0].trim()] = ss[1].trim() + } + } + } + } + oldValue = res + } + }) + } + handleEvent(dom, name, value, data, env) { + let actionName = name.slice(1).split('.') + let evtMap = { 'self': false, 'prevent': false, 'stop': false } + let evt = actionName[0] + if (evt === 'mounted') { + this.onMountedRun(dom, (d) => { + let cb = vproxy.Run(value, data, env) + if (typeof cb === 'function') { + (function() { + })(); + cb(d) + } + }, false) + } else if (evt === 'outerclick') { + let func = (e) => { + let cb = vproxy.Run(value, data, env, { $event: e }) + if (typeof cb === 'function') { + cb(e) + } + } + utils.AddClicker(dom, 'outer', func) + } else if (utils.EventsList.indexOf(evt) !== -1) { + if (evt === 'keydown' || evt === 'keyup' || evt === 'keypress') { + if (dom.tagName !== 'INPUT' && dom.tagName !== 'TEXTAREA') { + dom.setAttribute('tabindex', '0') + } + } + let func = (e) => { + let cb = vproxy.Run(value, data, env, { $event: e }) + if (typeof cb === 'function') { + cb(e) + } + } + actionName.slice(1).forEach(k => { + if (k.startsWith('delay')) { + let delay = k.slice(5) + if (!delay) { + delay = 1000 + } else if (delay.endsWith('ms')) { + delay = Number(delay.slice(0, -2)) + } else if (delay.endsWith('s')) { + delay = Number(delay.slice(0, -1)) * 1000 + } else { + delay = Number(delay) + } + if (isNaN(delay)) { + delay = 1000 + } + func = (e) => { + let fc = dom['_' + evt] + if (fc && typeof fc === 'number') { + clearTimeout(fc) + } + dom['_' + evt] = setTimeout(() => { + let cb = vproxy.Run(value, data, env, { $event: e }) + if (typeof cb === 'function') { + cb(e) + } + }, delay) + } + } + evtMap[k] = true + }) + dom.addEventListener(evt, (e) => { + if (actionName.length > 1 && (evt === 'keydown' || evt == 'keyup' || evt == 'keypress')) { + let btn = actionName[1] + if (btn !== e.key?.toLowerCase()) { + return + } + } + if (evtMap['self'] && e.currentTarget !== e.target) { + return + } + if (evtMap['prevent']) { + e.preventDefault() + } + if (evtMap['stop']) { + e.stopPropagation() + } + func(e) + }) + } else { + dom.$vevent = dom.$vevent || {} + dom.$vevent[evt] = (...arg) => { + let cb = vproxy.Run(value, data, env, {}) + if (typeof cb === 'function') { + cb(...arg) + } + } + } + } + + parseTextNode(dom, data, env) { + // text node + let txt = dom.nodeValue.trim() + if (!txt) { + return + } + let match + let nstart = 0 + let start = -1; + let txtItems = [] + while ((match = varRegex.exec(txt)) !== null) { + if (match[0] === '{{') { + start = match.index + } else if (match[0] === '}}' && start >= 0) { + if (nstart !== start) { + txtItems.push(txt.slice(nstart, start)) + } + txtItems.push('') + let valStr = txt.slice(start + 2, match.index) + let valIdx = txtItems.length + start = -1 + nstart = match.index + 2 + vproxy.Watch(() => { + txtItems[valIdx - 1] = vproxy.Run(valStr, data, env) + if (typeof txtItems[valIdx - 1] === 'object') { + txtItems[valIdx - 1] = JSON.stringify(txtItems[valIdx - 1]) + } + dom.nodeValue = txtItems.join('') + }) + } + } + txtItems.push(txt.slice(nstart)) + dom.nodeValue = txtItems.join('') + } + + vforDomCache = {} + parseVfor(vfortxt, dom, data, env) { + dom.removeAttribute('v-for') + let matches = vforRegex.exec(vfortxt) + if (matches?.length === 6) { + let vforTag = document.createElement('div') + vforTag.style.display = 'none' + let vforTagID = vproxy.GenUniqueID() + this.vforDomCache[vforTagID] = {} + dom.parentNode.replaceChild(vforTag, dom) + vproxy.Watch(() => { + let value = matches[3] || matches[2] + let key = matches[4] + let iters = vproxy.Run(matches[5], data, env) + let cache = this.vforDomCache[vforTagID] + let rendereds = new Set() + + if (typeof iters === 'function') { + iters = iters() + } else if (typeof iters === 'number') { + iters = Array.from({ length: iters }, (_, i) => i) + } + if (iters === undefined || iters === null) { + iters = [] + } + // 访问长度,触发监听 + let _ = iters.length + if (typeof iters === 'object') { + let keys = Object.keys(iters) + let items = [] + for (let kid in keys) { + let k = keys[kid] + let vfk = '' + if (iters[k] && iters[k][vproxy.DataID]) { + vfk = iters[k][vproxy.DataID] + } else { + vfk = k + '.' + iters[k] + } + vfk = vforTagID + "." + vfk + rendereds.add(vfk) + items.push({ k, vfk, val: iters[k] }) + } + + // Cleanup removed nodes + for (let k of Object.keys(cache)) { + if (!rendereds.has(k)) { + if (cache[k] instanceof Array) { + cache[k].forEach(d => d.remove()) + } else { + cache[k].remove() + } + delete cache[k] + } + } + + // Update and Reorder (Backwards) + let refNode = vforTag + for (let i = items.length - 1; i >= 0; i--) { + let { k, vfk, val } = items[i] + let curDom = cache[vfk] + + if (curDom) { + if (key) { + curDom.$vforData[key] = k === '0' ? 0 : (Number(k) || k) + } + if (curDom.isConnected) { + if (curDom.nextSibling !== refNode) { + vforTag.parentNode.insertBefore(curDom, refNode) + } + refNode = curDom + } + continue + } + + let newDom = dom.cloneNode(true) + cache[vfk] = newDom + let tmpData = { [value]: val } + if (key) { + tmpData[key] = k === '0' ? 0 : (Number(k) || k) + } + tmpData = vproxy.Wrap(tmpData, data) + newDom.$vforData = tmpData + + vforTag.parentNode.insertBefore(newDom, refNode) + + let vif = dom.getAttribute('v-if') + if (!vif) { + this.parseDom(newDom, tmpData, env) + refNode = newDom + continue + } + + newDom.removeAttribute('v-if') + let watchid = -1 + watchid = vproxy.Watch(() => { + let dom = cache[vfk] + if (!dom) { + vproxy.Cancel(watchid) + return + } + let res = vproxy.Run(vif, tmpData, env) + if (res) { + if (!dom.vparsed) { + this.parseDom(dom, tmpData, env) + } + if (!dom.isConnected) { + let founded = false + let before = vforTag + for (let tmpvfk in cache) { + if (tmpvfk === vfk) { + founded = true + continue + } + if (founded && cache[tmpvfk].isConnected) { + before = cache[tmpvfk] + break + } + } + vforTag.parentNode.insertBefore(dom, before) + } + } else { + if (dom.isConnected) { + dom.remove() + } else { + this.onMountedRun(dom, (d) => { + dom.remove() + }) + } + } + }) + + if (newDom.isConnected) { + refNode = newDom + } + } + } else { + console.error('vfor iter object error:', [matches, iters, vfortxt, data]) + } + }) + } else { + console.error('vfor error:', vfortxt) + } + } + + parseVif(nodes, data, env) { + let ifCache = { now: document.createElement('div'), conds: [], doms: [] } + const handleIf = (cache) => { + let ifData = { now: cache.now, conds: cache.conds, doms: cache.doms } + let ifList = [] + for (let cid in ifData.conds) { + let c = ifData.conds[cid] + if (c === '') { + c = 'true' + } else { + c = 'Boolean(' + c + ')' + } + ifList.push(c) + } + let ifFc = `let res = [${ifList.join(',')}]\n return res.indexOf(true)` + vproxy.Watch(() => { + let res = vproxy.Run(ifFc, data, env) + let tmpDom = ifData.doms[res] + if (!tmpDom) { + tmpDom = document.createElement('div') + tmpDom.style.display = 'none' + } + return tmpDom + }, (tmpDom) => { + if (!tmpDom) { + return + } + this.onMountedRun(ifData.now, (d) => { + d.replaceWith(tmpDom) + ifData.now = tmpDom + }) + if (!tmpDom?.vparsed) { + this.parseDom(tmpDom, data, env) + } + }) + } + let childs = nodes.filter(d => { + if (!d.getAttribute || d.getAttribute('v-for')) { + return true + } + if (d.getAttribute('v-if') !== null) { + if (ifCache.conds.length > 0) { + handleIf(ifCache) + ifCache = { now: document.createElement('div'), conds: [], doms: [] } + } + d.replaceWith(ifCache.now) + // dom.replaceChild(ifCache.now, d) + ifCache.conds.push(d.getAttribute('v-if')) + d.removeAttribute('v-if') + ifCache.doms.push(d) + return false + } else if (d.getAttribute('v-else-if') !== null) { + ifCache.conds.push(d.getAttribute('v-else-if')) + d.removeAttribute('v-else-if') + ifCache.doms.push(d) + d.remove() + return false + } else if (d.getAttribute('v-else') !== null) { + ifCache.conds.push('') + d.removeAttribute('v-else') + ifCache.doms.push(d) + d.remove() + return false + } + return true + }) + if (ifCache.conds.length > 0) { + handleIf(ifCache) + } + return childs + } + + + /** + * @param {HTMLElement} dom + * */ + parseSlots(dom, data, env) { + // 先插入dom,后解析,避免slot搭配v-for,v-if使用出现bug + let slotof = dom.getAttribute('vrefof') + let refDom = dom.closest(`*[vref='${slotof}']`) + if (!refDom) { + // TODO + this.onMountedRun(dom, (d) => { + this.parseSlots(d, data, env) + }) + return + } + while (true) { + let tmp = refDom?.parentNode.closest('*[vref]') + if (!tmp) { + break + } + if (tmp.getAttribute('vref') === slotof) { + refDom = tmp + } else { + break + } + } + let sName = dom.getAttribute('name') || '' + if (dom.getAttribute(':name')) { + let nameVal = dom.getAttribute(':name') + dom.removeAttribute(':name') + sName = vproxy.Run(nameVal, data, env) + } + // + if (!dom.originContent) { + dom.$originContent = Array.from(dom.childNodes) + dom.innerHTML = '' + } + // slot模板 + dom.$slotCache = {} + vproxy.Watch(() => { + let slots = refDom.$refSlots || {} + // slot数据域 + let slotsData = refDom.$refScope || {} + let sNodes = slots[sName] + if (sNodes && sNodes.length > 0) { + let hashID = sNodes[0].hashID + if (!hashID) { + hashID = vproxy.GenUniqueID() + sNodes[0].hashID = hashID + } else if (dom.$slotCache[hashID]) { + dom.innerHTML = '' + dom.append(...dom.$slotCache[hashID]) + return + } + dom.innerHTML = '' + sNodes = sNodes.map(n => n.cloneNode(true)) + dom.append(...sNodes) + let tmpSlotsData = slotsData + if (dom.getAttribute('vbind') !== null) { + let vbindAttrs = dom.getAttribute('vbind').split(',').map(a => a.trim()) + tmpSlotsData = vproxy.Wrap({}) + vbindAttrs.forEach(a => { + if (data.hasOwnProperty(a)) { + tmpSlotsData[a] = data[a] + } + }) + // tmpSlotsData = recordGet(dom.getAttribute('vbind'), data) + vproxy.SetDataRoot(tmpSlotsData, slotsData) + } + let sNodeVrefof = '' + sNodes.find(n => { + if (n.getAttribute && n.getAttribute('vrefof')) { + sNodeVrefof = n.getAttribute('vrefof') + return true + } + return false + }) + let sNodesEnv = env + if (sNodeVrefof) { + let sNodeVref = dom.closest(`*[vref='${sNodeVrefof}']`) + sNodesEnv = sNodeVref?.$env || env + } + sNodes = this.parseVif(sNodes, tmpSlotsData, sNodesEnv) + sNodes.forEach((n) => this.parseDom(n, tmpSlotsData, sNodesEnv)) + dom.$slotCache[hashID] = sNodes + } else { + dom.innerHTML = '' + dom.append(...dom.$originContent) + let parsed = false + dom.$originContent.forEach((n) => { + if (n.hasAttribute && n.vparsed) { + parsed = true + } + }) + if (!parsed) { + dom.$originContent = this.parseVif(dom.$originContent, data, env) + dom.$originContent.forEach((n) => this.parseDom(n, data, env)) + } + } + }) + this.parseAttrs(dom, data, env) + return dom + } + } + if (window.$vhtml) { + console.error('vhtml already exists.') + } else { + window.$vhtml = new vhtml(document.body) + console.log('vhtml loaded.') + } +})(); diff --git a/ui/vhtml/vbus.js b/ui/vhtml/vbus.js new file mode 100644 index 0000000..045c8ef --- /dev/null +++ b/ui/vhtml/vbus.js @@ -0,0 +1,138 @@ +/* + * vbus.js + * Copyright (C) 2025 veypi + * + * Distributed under terms of the MIT license. + */ + + +class EventBus { + constructor() { + // 存储事件监听器的对象 + this.events = {}; + } + + /** + * 订阅事件 + * @param {string} eventName - 事件名称 + * @param {Function} callback - 回调函数 + * @param {Object} context - 执行上下文(可选) + * @returns {Function} 取消订阅的函数 + */ + on(eventName, callback, context = null) { + if (typeof callback !== 'function') { + throw new Error('回调函数必须是一个函数'); + } + + if (!this.events[eventName]) { + this.events[eventName] = []; + } + + const listener = { callback, context }; + this.events[eventName].push(listener); + + // 返回取消订阅的函数 + return () => this.off(eventName, callback, context); + } + + /** + * 一次性事件监听 + * @param {string} eventName - 事件名称 + * @param {Function} callback - 回调函数 + * @param {Object} context - 执行上下文(可选) + * @returns {Function} 取消订阅的函数 + */ + once(eventName, callback, context = null) { + const onceWrapper = (...args) => { + this.off(eventName, onceWrapper, context); + callback.apply(context, args); + }; + + return this.on(eventName, onceWrapper, context); + } + + /** + * 取消事件订阅 + * @param {string} eventName - 事件名称 + * @param {Function} callback - 要移除的回调函数(可选) + * @param {Object} context - 执行上下文(可选) + */ + off(eventName, callback = null, context = null) { + if (!this.events[eventName]) { + return; + } + + // 如果没有指定回调函数,移除该事件的所有监听器 + if (!callback) { + delete this.events[eventName]; + return; + } + + // 移除特定的监听器 + this.events[eventName] = this.events[eventName].filter(listener => { + return !(listener.callback === callback && listener.context === context); + }); + + // 如果该事件没有监听器了,删除该事件 + if (this.events[eventName].length === 0) { + delete this.events[eventName]; + } + } + + /** + * 触发事件 + * @param {string} eventName - 事件名称 + * @param {...any} args - 传递给回调函数的参数 + */ + emit(eventName, ...args) { + if (!this.events[eventName]) { + return; + } + + // 复制监听器数组,避免在执行过程中修改原数组导致的问题 + const listeners = [...this.events[eventName]]; + + listeners.forEach(listener => { + try { + listener.callback.apply(listener.context, args); + } catch (error) { + console.error(`事件 "${eventName}" 的监听器执行出错:`, error); + } + }); + } + + /** + * 获取事件的监听器数量 + * @param {string} eventName - 事件名称 + * @returns {number} 监听器数量 + */ + listenerCount(eventName) { + return this.events[eventName] ? this.events[eventName].length : 0; + } + + /** + * 获取所有事件名称 + * @returns {string[]} 事件名称数组 + */ + eventNames() { + return Object.keys(this.events); + } + + /** + * 移除所有事件监听器 + */ + removeAllListeners() { + this.events = {}; + } + + /** + * 检查是否有某个事件的监听器 + * @param {string} eventName - 事件名称 + * @returns {boolean} 是否有监听器 + */ + hasListeners(eventName) { + return this.listenerCount(eventName) > 0; + } +} + +export default EventBus; diff --git a/ui/vhtml/vcss.js b/ui/vhtml/vcss.js new file mode 100644 index 0000000..3369554 --- /dev/null +++ b/ui/vhtml/vcss.js @@ -0,0 +1,566 @@ +/* + * vcss.js + * Copyright (C) 2025 veypi + * + * Distributed under terms of the GPL license. + * simple css parser + */ + + + +class CSSParser { + constructor() { + this.scopeAttribute = ''; + this.scopeBody = '' + this.scopedKeyframes = new Map(); // 存储已处理的keyframe映射 + } + + /** + * 解析CSS文本并添加作用域 + * @param {string} cssText - CSS文本 + * @param {string} scope - 作用域标识符 + * @returns {string} - 处理后的CSS文本 + */ + parse(cssText, scope) { + this.scopeAttribute = `[vrefof="${scope}"]`; + this.scopeBody = `[vref="${scope}"]` + this.scopedKeyframes.clear(); + this.scopeSuffix = scope.replace(/[^a-zA-Z0-9]/g, ''); // 清理作用域后缀 + + // 移除注释 + cssText = this.removeComments(cssText); + + // 第一遍:收集所有keyframes名称 + this.collectKeyframes(cssText); + + // 第二遍:解析CSS规则并替换动画名称 + return this.parseRules(cssText); + } + + /** + * 收集所有keyframes名称 + * @param {string} cssText + */ + collectKeyframes(cssText) { + const keyframeRegex = /@keyframes\s+([^\s{]+)/gi; + let match; + + while ((match = keyframeRegex.exec(cssText)) !== null) { + const originalName = match[1]; + const scopedName = originalName + '-' + this.scopeSuffix; + this.scopedKeyframes.set(originalName, scopedName); + } + } + + /** + * 移除CSS注释 + * @param {string} cssText + * @returns {string} + */ + removeComments(cssText) { + return cssText.replace(/\/\*[\s\S]*?\*\//g, ''); + } + + /** + * 解析CSS规则 + * @param {string} cssText + * @returns {string} + */ + parseRules(cssText) { + let result = ''; + let i = 0; + + while (i < cssText.length) { + // 跳过空白字符 + while (i < cssText.length && /\s/.test(cssText[i])) { + result += cssText[i]; + i++; + } + + if (i >= cssText.length) break; + + // 检查是否是@规则 + if (cssText[i] === '@') { + const atRule = this.parseAtRule(cssText, i); + result += atRule.content; + i = atRule.endIndex; + } else { + // 普通CSS规则 + const rule = this.parseNormalRule(cssText, i); + result += rule.content; + i = rule.endIndex; + } + } + + return result; + } + + /** + * 解析@规则(如@media, @keyframes等) + * @param {string} cssText + * @param {number} startIndex + * @returns {object} + */ + parseAtRule(cssText, startIndex) { + let i = startIndex; + let atRuleContent = ''; + + // 读取@规则名称和参数 + while (i < cssText.length && cssText[i] !== '{') { + atRuleContent += cssText[i]; + i++; + } + + if (i >= cssText.length) { + return { content: atRuleContent, endIndex: i }; + } + + // 检查是否是@keyframes或@media + const atRuleName = atRuleContent.toLowerCase().trim(); + + if (atRuleName.startsWith('@keyframes')) { + return this.parseKeyframes(cssText, startIndex); + } else if (atRuleName.startsWith('@media')) { + return this.parseMedia(cssText, startIndex); + } else if (atRuleName.startsWith('@supports')) { + return this.parseSupports(cssText, startIndex); + } else { + // 其他@规则,查找匹配的大括号 + const braceContent = this.findMatchingBrace(cssText, i); + return { + content: atRuleContent + braceContent.content, + endIndex: braceContent.endIndex + }; + } + } + + /** + * 解析@keyframes规则 + * @param {string} cssText + * @param {number} startIndex + * @returns {object} + */ + parseKeyframes(cssText, startIndex) { + let i = startIndex; + let result = ''; + + // 读取@keyframes声明 + while (i < cssText.length && cssText[i] !== '{') { + result += cssText[i]; + i++; + } + + if (i >= cssText.length) { + return { content: result, endIndex: i }; + } + + // 处理keyframes内容 + const braceContent = this.findMatchingBrace(cssText, i); + const keyframesContent = braceContent.content; + + // 为keyframes名称添加作用域 + const keyframeName = this.extractKeyframeName(result); + const scopedKeyframeName = this.scopedKeyframes.get(keyframeName); + if (scopedKeyframeName) { + result = result.replace(keyframeName, scopedKeyframeName); + } + + result += keyframesContent; + + return { + content: result, + endIndex: braceContent.endIndex + }; + } + + /** + * 提取keyframe名称 + * @param {string} keyframeDeclaration + * @returns {string} + */ + extractKeyframeName(keyframeDeclaration) { + const match = keyframeDeclaration.match(/@keyframes\s+([^\s{]+)/i); + return match ? match[1] : ''; + } + + /** + * 解析@media规则 + * @param {string} cssText + * @param {number} startIndex + * @returns {object} + */ + parseMedia(cssText, startIndex) { + let i = startIndex; + let result = ''; + + // 读取@media声明 + while (i < cssText.length && cssText[i] !== '{') { + result += cssText[i]; + i++; + } + + if (i >= cssText.length) { + return { content: result, endIndex: i }; + } + + result += '{'; + i++; // 跳过开始的 '{' + + // 解析@media内部的CSS规则 + let braceLevel = 1; + let innerCss = ''; + + while (i < cssText.length && braceLevel > 0) { + if (cssText[i] === '{') { + braceLevel++; + } else if (cssText[i] === '}') { + braceLevel--; + if (braceLevel === 0) { + break; + } + } + innerCss += cssText[i]; + i++; + } + + // 递归处理@media内部的CSS规则 + const processedInnerCss = this.parseRules(innerCss); + result += processedInnerCss; + + if (i < cssText.length && cssText[i] === '}') { + result += '}'; + i++; + } + + return { + content: result, + endIndex: i + }; + } + + /** + * 解析@supports规则 + * @param {string} cssText + * @param {number} startIndex + * @returns {object} + */ + parseSupports(cssText, startIndex) { + return this.parseMedia(cssText, startIndex); + } + + /** + * 解析普通CSS规则 + * @param {string} cssText + * @param {number} startIndex + * @returns {object} + */ + parseNormalRule(cssText, startIndex) { + let i = startIndex; + let selector = ''; + + // 读取选择器 + while (i < cssText.length && cssText[i] !== '{') { + selector += cssText[i]; + i++; + } + + if (i >= cssText.length) { + return { content: selector, endIndex: i }; + } + + // 处理选择器添加作用域 + const scopedSelector = this.addScopeToSelector(selector.trim()); + + // 读取CSS规则体并处理动画名称 + const braceContent = this.findMatchingBrace(cssText, i); + const processedContent = this.processRuleContent(braceContent.content); + + return { + content: scopedSelector + processedContent, + endIndex: braceContent.endIndex + }; + } + + /** + * 处理CSS规则内容,替换动画名称 + * @param {string} content + * @returns {string} + */ + processRuleContent(content) { + let processedContent = content; + + // 处理 animation 属性 + processedContent = processedContent.replace( + /animation\s*:\s*([^;]+);/gi, + (match, animationValue) => { + const processedValue = this.processAnimationValue(animationValue); + return `animation: ${processedValue};`; + } + ); + + // 处理 animation-name 属性 + processedContent = processedContent.replace( + /animation-name\s*:\s*([^;]+);/gi, + (match, animationNames) => { + const processedNames = this.processAnimationNames(animationNames); + return `animation-name: ${processedNames};`; + } + ); + + return processedContent; + } + + /** + * 处理animation属性值 + * @param {string} animationValue + * @returns {string} + */ + processAnimationValue(animationValue) { + // animation 可能包含多个动画,用逗号分隔 + const animations = animationValue.split(',').map(anim => anim.trim()); + + return animations.map(animation => { + const parts = animation.split(/\s+/); + + // 第一个非时间、非数字、非关键字的值通常是动画名称 + for (let i = 0; i < parts.length; i++) { + const part = parts[i]; + + // 跳过时间值 (如 0.3s, 200ms) + if (/^\d+(\.\d+)?(s|ms)$/.test(part)) continue; + + // 跳过数字值 (如 iteration count) + if (/^\d+(\.\d+)?$/.test(part)) continue; + + // 跳过CSS关键字 + if (['ease', 'ease-in', 'ease-out', 'ease-in-out', 'linear', 'infinite', + 'normal', 'reverse', 'alternate', 'alternate-reverse', 'forwards', + 'backwards', 'both', 'running', 'paused'].includes(part)) continue; + + // 跳过贝塞尔曲线 + if (part.startsWith('cubic-bezier(')) continue; + + // 这应该是动画名称 + const scopedName = this.scopedKeyframes.get(part); + if (scopedName) { + parts[i] = scopedName; + } + break; + } + + return parts.join(' '); + }).join(', '); + } + + /** + * 处理animation-name属性值 + * @param {string} animationNames + * @returns {string} + */ + processAnimationNames(animationNames) { + return animationNames.split(',').map(name => { + const trimmedName = name.trim(); + const scopedName = this.scopedKeyframes.get(trimmedName); + return scopedName || trimmedName; + }).join(', '); + } + + /** + * 为选择器添加作用域 + * @param {string} selector + * @returns {string} + */ + addScopeToSelector(selector) { + if (!selector.trim()) return selector; + + // 分割多个选择器(用逗号分隔) + const selectors = selector.split(',').map(sel => sel.trim()); + + const scopedSelectors = selectors.map(sel => { + return this.addScopeToSingleSelector(sel); + }); + + return scopedSelectors.join(', '); + } + + /** + * 为单个选择器添加作用域 + * @param {string} selector + * @returns {string} + */ + addScopeToSingleSelector(selector) { + if (!selector.trim()) return selector; + + // 处理伪元素选择器 - 在伪元素前添加作用域 + if (selector.includes('::')) { + const parts = selector.split('::'); + const mainPart = parts[0]; + const pseudoElement = '::' + parts.slice(1).join('::'); + + // 为主要部分添加作用域 + const scopedMain = this.addScopeToSelectorPart(mainPart); + return scopedMain + pseudoElement; + } + + // 处理伪类选择器 - 在伪类前添加作用域 + if (selector.includes(':') && !selector.includes('::')) { + const pseudoMatch = selector.match(/^([^:]+)(:.+)$/); + if (pseudoMatch) { + const mainPart = pseudoMatch[1]; + const pseudoClass = pseudoMatch[2]; + + // 为主要部分添加作用域 + const scopedMain = this.addScopeToSelectorPart(mainPart); + return scopedMain + pseudoClass; + } + } + + // 处理特殊选择器 + if (selector === '*' || selector.startsWith('@')) { + return selector; + } + + // 处理复合选择器 + return this.addScopeToSelectorPart(selector); + } + + /** + * 为选择器部分添加作用域 + * @param {string} selectorPart + * @returns {string} + */ + addScopeToSelectorPart(selectorPart) { + // 处理组合器选择器(>、+、~、空格) + const combinatorRegex = /(\s*[>+~]\s*|\s+)/; + + if (combinatorRegex.test(selectorPart)) { + // 分割选择器,但保留组合器 + const parts = selectorPart.split(combinatorRegex); + if (/^body(?:$|[:\[ ])/.test(parts[0])) { + parts[0] = this.scopeBody + parts[0].slice(4) + return parts.join(''); + } + if (/^:root(?:$|[:\[ ])/.test(parts[0])) { + parts[0] = this.scopeBody + parts[0].slice(5) + return parts.join(''); + } + + // 只在最后一个选择器部分添加作用域 + for (let i = parts.length - 1; i >= 0; i--) { + if (parts[i].trim() && !combinatorRegex.test(parts[i])) { + let tag = parts[i].trim() + if (/^body(?:$|[:\[ ])/.test(tag)) { + parts[i] = this.scopeBody + tag.slice(4) + } else if (/^:root(?:$:[$:\[ ])/.test(tag)) { + parts[i] = this.scopeBody + tag.slice(5) + } else { + parts[i] = parts[i].trim() + this.scopeAttribute; + } + break; + } + } + + return parts.join(''); + } + selectorPart = selectorPart.trim() + let tag = selectorPart.trim() + if (/^body(?:$|[:\[ ])/.test(tag)) { + return this.scopeBody + tag.slice(4) + } else if (/^:root(?:$:[$:\[ ])/.test(tag)) { + return this.scopeBody + tag.slice(5) + } else { + return tag + this.scopeAttribute; + } + } + + /** + * 查找匹配的大括号 + * @param {string} cssText + * @param {number} startIndex + * @returns {object} + */ + findMatchingBrace(cssText, startIndex) { + let i = startIndex; + let content = ''; + let braceLevel = 0; + + while (i < cssText.length) { + content += cssText[i]; + + if (cssText[i] === '{') { + braceLevel++; + } else if (cssText[i] === '}') { + braceLevel--; + if (braceLevel === 0) { + i++; + break; + } + } + i++; + } + + return { + content: content, + endIndex: i + }; + } +} + +// 使用示例 +const parser = new CSSParser(); + +// 示例CSS +const cssText = ` + body{} + .container::before, .a { + content: ""; + animation-name: fadeIn, slideUp; + animation: slideIn 0.5s infinite alternate; + } + + @keyframes slideIn { + from { + transform: translateX(-100%); + } + to { + transform: translateX(0); + } + } + + @keyframes fadeIn { + from { opacity: 0; } + to { opacity: 1; } + } + + @keyframes slideUp { + from { transform: translateY(100%); } + to { transform: translateY(0); } + } + + @media (max-width: 768px) { + .container { + font-size: 14px; + animation: slideIn 0.2s ease-out; + } + + .item { + margin: 5px; + } + } + + .box > .child { + color: green; + } + + .box + .sibling { + margin-top: 20px; + } +`; + +// 解析并添加作用域 +// console.log(parser.parse(cssText, 'comasd-123')); + +// 导出类 +export default parser; + +export { CSSParser } diff --git a/ui/vhtml/vdev.js b/ui/vhtml/vdev.js new file mode 100644 index 0000000..0052b3b --- /dev/null +++ b/ui/vhtml/vdev.js @@ -0,0 +1,70 @@ +/* + * vdev.js + * Copyright (C) 2025 veypi + * + * Distributed under terms of the MIT license. + */ + +import DivSelectorPlugin from './vdevselect.js' + +let isSetup = false; +let divSelector = null; + +const postMessage = (typ, args) => { + if (!isSetup) return; // 未初始化前不发送消息 + if (typeof args === 'string' || typeof args === 'number') { + args = { value: args } + } + window.parent.postMessage(Object.assign({ type: typ, from: 'vdev' }, args), '*') +} + +// 延迟执行的初始化函数 +const initializeVdev = () => { + // 在初始化时创建 divSelector 实例 + divSelector = new DivSelectorPlugin(); + + postMessage('iframe-loaded') + divSelector.postMessage = postMessage + + window.addEventListener('keyup', (event) => { + if (event.key === 'Escape') { + postMessage('key-esc') + } + }) + + setTimeout(() => { + if (window.$vhtml && window.$vhtml.$router) { + $vhtml.$router.onChange((url) => { + postMessage('url-change', url.fullPath) + }) + } + }, 100) + + window.addEventListener('message', (event) => { + const data = event.data; + console.log(data) + if (data.from != 'vhtml') { + return + } + switch (data.type) { + case 'reload': + window.location.reload() + break; + case 'magic': + if (divSelector && divSelector.isActive) { + divSelector.deactivate() + } else if (divSelector) { + divSelector.activate() + } + break + } + }); +} + +function setup() { + if (isSetup) return; // 防止重复初始化 + isSetup = true; + initializeVdev(); +} + +export default setup diff --git a/ui/vhtml/vdevselect.js b/ui/vhtml/vdevselect.js new file mode 100644 index 0000000..c59f518 --- /dev/null +++ b/ui/vhtml/vdevselect.js @@ -0,0 +1,620 @@ +/* + * vdev-select.js + * Copyright (C) 2025 veypi + * + * Distributed under terms of the MIT license. + */ + +const copyToClipboard = async (text) => { + if (navigator.clipboard && navigator.clipboard.writeText) { + return navigator.clipboard.writeText(text) + } + prompt('http环境无法自动复制,请手动复制内容到剪贴板:', text) + return new Promise((resolve) => { }) +} + +/** + * Div Selector Plugin + * 用于选择页面div元素并高亮显示的插件 + */ +class DivSelectorPlugin { + postMessage = (typ, args) => { } + constructor(options = {}) { + this.options = { + highlightColor: '#007bff', + overlayColor: 'rgba(0, 123, 255, 0.1)', + borderWidth: '2px', + zIndex: 10000, + showTagName: true, + ...options + }; + + this.isActive = false; + this.selectedElement = null; + this.currentHoverElement = null; + this.overlay = null; + this.selectedOverlay = null; + this.tooltip = null; + this.selectedTooltip = null; + this.actionPanel = null; + this.originalCursor = ''; + + this.init(); + } + + init() { + this.createStyles(); + this.bindEvents(); + } + + createStyles() { + const style = document.createElement('style'); + style.textContent = ` + .div-selector-overlay { + position: fixed; + pointer-events: none; + border: ${this.options.borderWidth} solid ${this.options.highlightColor}; + background: ${this.options.overlayColor}; + z-index: ${this.options.zIndex}; + transition: all 0.2s ease; + box-sizing: border-box; + } + + .div-selector-selected { + position: fixed; + pointer-events: none; + border: ${this.options.borderWidth} solid #28a745; + background: rgba(40, 167, 69, 0.1); + z-index: ${this.options.zIndex - 1}; + box-sizing: border-box; + } + + .div-selector-tooltip { + position: fixed; + background: rgba(51, 51, 51, 0.95); + cursor:pointer; + color: white; + padding: 8px 12px; + border-radius: 6px; + font-size: 12px; + font-family: 'Consolas', 'Monaco', 'Courier New', monospace; + z-index: ${this.options.zIndex + 1}; + user-select: none; + box-shadow: 0 2px 8px rgba(0,0,0,0.3); + border: 1px solid rgba(255,255,255,0.1); + backdrop-filter: blur(4px); + } + + .div-selector-tooltip.hover { + background: rgba(0, 123, 255, 0.9); + } + + .div-selector-tooltip.selected { + background: rgba(40, 167, 69, 0.9); + border-color: rgba(40, 167, 69, 0.3); + } + + .div-selector-actions { + position: fixed; + background: white; + border: 1px solid #ddd; + border-radius: 8px; + padding: 8px; + z-index: ${this.options.zIndex + 2}; + box-shadow: 0 4px 16px rgba(0,0,0,0.15); + display: flex; + gap: 6px; + min-width: 30px; + backdrop-filter: blur(8px); + } + + .div-selector-btn { + padding: 4px 6px; + border: 1px solid #ddd; + background: white; + border-radius: 6px; + cursor: pointer; + font-size: 12px; + transition: all 0.2s ease; + text-align: left; + white-space: nowrap; + } + + .div-selector-btn:hover { + background: #f8f9fa; + transform: translateX(2px); + } + + .div-selector-btn.danger { + color: #dc3545; + border-color: #dc3545; + } + + .div-selector-btn.danger:hover { + background: #dc3545; + color: white; + } + + .div-selector-btn.primary { + background: #007bff; + color: white; + border-color: #007bff; + } + + .div-selector-btn.primary:hover { + background: #0056b3; + } + + .div-selector-active { + cursor: crosshair !important; + } + `; + document.head.appendChild(style); + } + + bindEvents() { + this.handleMouseMove = this.handleMouseMove.bind(this); + this.handleClick = this.handleClick.bind(this); + this.handleScroll = this.handleScroll.bind(this); + this.handleResize = this.handleResize.bind(this); + } + + activate() { + if (this.isActive) return; + + this.isActive = true; + this.originalCursor = document.body.style.cursor; + document.body.classList.add('div-selector-active'); + + document.addEventListener('mousemove', this.handleMouseMove); + document.addEventListener('click', this.handleClick); + window.addEventListener('scroll', this.handleScroll); + window.addEventListener('resize', this.handleResize); + + this.createOverlay(); + this.createTooltip(); + + } + + deactivate() { + if (!this.isActive) return; + + this.isActive = false; + document.body.style.cursor = this.originalCursor; + document.body.classList.remove('div-selector-active'); + + document.removeEventListener('mousemove', this.handleMouseMove); + document.removeEventListener('click', this.handleClick); + window.removeEventListener('scroll', this.handleScroll); + window.removeEventListener('resize', this.handleResize); + + this.removeOverlay(); + this.removeTooltip(); + // this.clearSelection(); + + console.log('Div Selector Plugin deactivated.'); + } + + handleMouseMove(e) { + if (!this.isActive) return; + + const element = document.elementFromPoint(e.clientX, e.clientY); + if (!element) return; + + // 忽略插件自身的元素 + if (this.isPluginElement(element)) return; + + // 查找最近的div元素 + const divElement = element.tagName === 'DIV' ? element : element.closest('div,[vref]'); + if (!divElement || this.isPluginElement(divElement)) return; + + // 如果已选中元素,不要高亮显示它 + if (this.selectedElement === divElement) return; + + this.currentHoverElement = divElement; + this.highlightElement(divElement); + this.updateHoverTooltip(divElement); + } + + handleClick(e) { + if (!this.isActive) return; + + const element = document.elementFromPoint(e.clientX, e.clientY); + if (!element) return; + + // 忽略插件自身的元素 + if (this.isPluginElement(element)) return; + + e.preventDefault(); + e.stopPropagation(); + + const divElement = element.tagName === 'DIV' ? element : element.closest('div'); + if (!divElement || this.isPluginElement(divElement)) return; + + this.selectElement(divElement); + this.deactivate() + } + + handleScroll() { + if (this.selectedElement) { + this.updateSelectedOverlay(); + this.updateSelectedTooltip(); + this.updateActionPanelPosition(); + } + if (this.currentHoverElement && !this.selectedElement) { + this.highlightElement(this.currentHoverElement); + this.updateHoverTooltip(this.currentHoverElement); + } + } + + handleResize() { + if (this.selectedElement) { + this.updateSelectedOverlay(); + this.updateSelectedTooltip(); + this.updateActionPanelPosition(); + } + } + + isPluginElement(element) { + return element.closest('.div-selector-overlay, .div-selector-selected, .div-selector-tooltip, .div-selector-actions'); + } + + createOverlay() { + this.overlay = document.createElement('div'); + this.overlay.className = 'div-selector-overlay'; + this.overlay.style.display = 'none'; + document.body.appendChild(this.overlay); + } + + createSelectedOverlay() { + this.selectedOverlay = document.createElement('div'); + this.selectedOverlay.className = 'div-selector-selected'; + document.body.appendChild(this.selectedOverlay); + } + + createTooltip() { + this.tooltip = document.createElement('div'); + this.tooltip.className = 'div-selector-tooltip hover'; + this.tooltip.style.display = 'none'; + document.body.appendChild(this.tooltip); + } + + createSelectedTooltip() { + this.selectedTooltip = document.createElement('div'); + this.selectedTooltip.className = 'div-selector-tooltip selected'; + document.body.appendChild(this.selectedTooltip); + } + + highlightElement(element) { + if (!this.overlay) return; + + const rect = element.getBoundingClientRect(); + + this.overlay.style.display = 'block'; + this.overlay.style.left = rect.left + 'px'; + this.overlay.style.top = rect.top + 'px'; + this.overlay.style.width = rect.width + 'px'; + this.overlay.style.height = rect.height + 'px'; + } + + updateHoverTooltip(element) { + if (!this.tooltip) return; + + const elementInfo = this.getElementInfo(element); + const rect = element.getBoundingClientRect(); + + this.tooltip.textContent = elementInfo; + this.tooltip.style.display = 'block'; + + // 计算tooltip位置 - 左上角,稍微偏移避免遮挡 + let left = rect.left - 8; + let top = rect.top - this.tooltip.offsetHeight - 8; + + // 确保不超出视窗 + if (left < 0) left = 8; + if (top < 0) top = rect.top + 8; + + this.tooltip.style.left = left + 'px'; + this.tooltip.style.top = top + 'px'; + } + + selectElement(element) { + // 清除之前的选择 + this.clearSelection(); + + this.selectedElement = element; + + // 创建选中状态的覆盖层和tooltip + this.createSelectedOverlay(); + this.createSelectedTooltip(); + this.updateSelectedOverlay(); + this.updateSelectedTooltip(); + + // 隐藏悬停效果 + if (this.overlay) { + this.overlay.style.display = 'none'; + } + if (this.tooltip) { + this.tooltip.style.display = 'none'; + } + + // 显示操作面板 + this.showActionPanel(); + + console.log('Element selected:', element); + } + + updateSelectedOverlay() { + if (!this.selectedOverlay || !this.selectedElement) return; + + const rect = this.selectedElement.getBoundingClientRect(); + + this.selectedOverlay.style.left = rect.left + 'px'; + this.selectedOverlay.style.top = rect.top + 'px'; + this.selectedOverlay.style.width = rect.width + 'px'; + this.selectedOverlay.style.height = rect.height + 'px'; + } + + updateSelectedTooltip() { + if (!this.selectedTooltip || !this.selectedElement) return; + + const elementInfo = this.getElementInfo(this.selectedElement); + let vref = this.getFilePath(this.selectedElement) + const rect = this.selectedElement.getBoundingClientRect(); + this.selectedTooltip.addEventListener('click', e => { + if (vref) { + this.postMessage('fs-open', vref) + } + e.preventDefault() + e.stopPropagation() + }) + + this.selectedTooltip.textContent = `✓ ${elementInfo}`; + + // 计算tooltip位置 - 选中框的左上角 + let left = rect.left - 8; + let top = rect.top - this.selectedTooltip.offsetHeight - 8; + + // 确保不超出视窗 + if (left < 0) left = 8; + if (top < 0) top = rect.top + 8; + + this.selectedTooltip.style.left = left + 'px'; + this.selectedTooltip.style.top = top + 'px'; + } + + showActionPanel() { + this.removeActionPanel(); + + const rect = this.selectedElement.getBoundingClientRect(); + + this.actionPanel = document.createElement('div'); + this.actionPanel.className = 'div-selector-actions'; + + // 计算位置 - 放在右上角 + const panelWidth = 180; // 预估宽度 + const panelHeight = 40; // 预估高度 + + let left = rect.right - panelWidth; + let top = rect.top + 6; + + // 确保不超出视窗 + if (left + panelWidth > window.innerWidth) { + left = rect.left - panelWidth - 8; + } + if (left < 0) left = 8; + + if (top + panelHeight > window.innerHeight) { + top = window.innerHeight - panelHeight - 8; + } + if (top < 0) top = 8; + + this.actionPanel.style.left = left + 'px'; + this.actionPanel.style.top = top + 'px'; + + // 创建操作按钮 + const buttons = [ + { text: '📋', action: () => this.copySelector(this.selectedElement) }, + // { text: '🔍', action: () => this.copyXPath(this.selectedElement) }, + // { text: '👁️', action: () => this.viewStyles(this.selectedElement) }, + // { text: '📍', action: () => this.clearSelection() }, + { text: 'x', action: () => this.clearSelection() }, + ]; + + buttons.forEach(btn => { + const button = document.createElement('button'); + button.className = `div-selector-btn ${btn.class || ''}`; + button.textContent = btn.text; + button.onclick = btn.action; + this.actionPanel.appendChild(button); + }); + + document.body.appendChild(this.actionPanel); + } + + updateActionPanelPosition() { + if (!this.actionPanel || !this.selectedElement) return; + + const rect = this.selectedElement.getBoundingClientRect(); + const panelWidth = this.actionPanel.offsetWidth; + const panelHeight = this.actionPanel.offsetHeight; + + let left = rect.right - panelWidth + 8; + let top = rect.top - 8; + + // 确保不超出视窗 + if (left + panelWidth > window.innerWidth) { + left = rect.left - panelWidth - 8; + } + if (left < 0) left = 8; + + if (top + panelHeight > window.innerHeight) { + top = window.innerHeight - panelHeight - 8; + } + if (top < 0) top = 8; + + this.actionPanel.style.left = left + 'px'; + this.actionPanel.style.top = top + 'px'; + } + + clearSelection() { + this.selectedElement = null; + + if (this.selectedOverlay) { + this.selectedOverlay.remove(); + this.selectedOverlay = null; + } + + if (this.selectedTooltip) { + this.selectedTooltip.remove(); + this.selectedTooltip = null; + } + + this.removeActionPanel(); + + console.log('Selection cleared'); + } + + getElementInfo(element) { + const rect = element.getBoundingClientRect(); + let vref = element.getAttribute('vref') + if (!vref) { + vref = element.closest('[vref]').getAttribute('vref') + vref += "." + element.tagName.toLowerCase(); + } + return `${vref} (${Math.round(rect.width)}×${Math.round(rect.height)})`; + } + + getFilePath(element) { + let vref = element.getAttribute('vref') + if (!vref) { + vref = element.closest('[vref]').getAttribute('vref') + } + if (vref) { + vref = '/ui' + vref + '.html' + } + return vref + } + + copySelector(element) { + let vref = this.getFilePath(element) + copyToClipboard(vref).then(() => { + console.log('CSS Selector copied:', selector); + this.showNotification('📋 CSS选择器已复制到剪贴板'); + }); + } + + copyXPath(element) { + const xpath = this.generateXPath(element); + copyToClipboard(xpath).then(() => { + console.log('XPath copied:', xpath); + this.showNotification('🔍 XPath已复制到剪贴板'); + }); + } + + viewStyles(element) { + const styles = window.getComputedStyle(element); + const importantStyles = [ + 'display', 'position', 'width', 'height', 'margin', 'padding', + 'background-color', 'color', 'font-size', 'border', 'z-index', 'opacity' + ]; + + let styleInfo = '📊 重要样式属性:\n\n'; + importantStyles.forEach(prop => { + styleInfo += `${prop}: ${styles.getPropertyValue(prop)}\n`; + }); + + alert(styleInfo); + } + + + showNotification(message) { + const notification = document.createElement('div'); + notification.style.cssText = ` + position: fixed; + top: 20px; + right: 20px; + background: linear-gradient(135deg, #28a745, #20c997); + color: white; + padding: 12px 18px; + border-radius: 8px; + z-index: ${this.options.zIndex + 10}; + font-size: 14px; + box-shadow: 0 4px 12px rgba(0,0,0,0.2); + transform: translateX(100%); + transition: transform 0.3s ease; + `; + notification.textContent = message; + document.body.appendChild(notification); + + // 动画显示 + setTimeout(() => { + notification.style.transform = 'translateX(0)'; + }, 100); + + // 自动隐藏 + setTimeout(() => { + notification.style.transform = 'translateX(100%)'; + setTimeout(() => { + notification.remove(); + }, 300); + }, 2500); + } + + generateXPath(element) { + if (element.id) { + return `//*[@id="${element.id}"]`; + } + + const path = []; + while (element && element.nodeType === Node.ELEMENT_NODE) { + let index = 0; + let hasFollowingSiblings = false; + let hasPrecedingSiblings = false; + + for (let sibling = element.previousSibling; sibling; sibling = sibling.previousSibling) { + if (sibling.nodeType === Node.ELEMENT_NODE && sibling.nodeName === element.nodeName) { + hasPrecedingSiblings = true; + index++; + } + } + + for (let sibling = element.nextSibling; sibling && !hasFollowingSiblings; sibling = sibling.nextSibling) { + if (sibling.nodeType === Node.ELEMENT_NODE && sibling.nodeName === element.nodeName) { + hasFollowingSiblings = true; + } + } + + const tagName = element.nodeName.toLowerCase(); + const pathIndex = (hasPrecedingSiblings || hasFollowingSiblings) ? `[${index + 1}]` : ''; + path.unshift(tagName + pathIndex); + element = element.parentNode; + if (element === document.body) break; + } + + return path.length ? '/' + path.join('/') : null; + } + + removeOverlay() { + if (this.overlay) { + this.overlay.remove(); + this.overlay = null; + } + } + + removeTooltip() { + if (this.tooltip) { + this.tooltip.remove(); + this.tooltip = null; + } + } + + removeActionPanel() { + if (this.actionPanel) { + this.actionPanel.remove(); + this.actionPanel = null; + } + } +} + +export default DivSelectorPlugin diff --git a/ui/vhtml/verror.js b/ui/vhtml/verror.js new file mode 100644 index 0000000..ddd74aa --- /dev/null +++ b/ui/vhtml/verror.js @@ -0,0 +1,89 @@ +/* + * verror.js + * Copyright (C) 2025 veypi + * + * Distributed under terms of the MIT license. + */ +class ErrorCollector { + constructor() { + this.errorQueue = []; + this.init(); + } + + init() { + // 监听未处理的 Promise 拒绝 + window.addEventListener('unhandledrejection', (event) => { + this.handleError({ + type: 'unhandledrejection', + message: event.reason.message || String(event.reason), + stack: event.reason.stack, + timestamp: new Date().toISOString(), + userAgent: navigator.userAgent, + url: window.location.href, + promiseRejection: true + }); + }); + + // 监听 JavaScript 错误 + window.addEventListener('error', (event) => { + if (event.target === window) { + this.handleError({ + type: 'javascript-error', + message: event.message, + source: event.filename, + line: event.lineno, + column: event.colno, + stack: event.error ? event.error.stack : null, + timestamp: new Date().toISOString(), + userAgent: navigator.userAgent, + url: window.location.href + }); + } + }); + + } + + handleError(errorInfo) { + console.error('Error collected:', errorInfo); + this.queueError(errorInfo); + } + + queueError(errorInfo) { + this.errorQueue.push(errorInfo); + + // 限制队列大小 + if (this.errorQueue.length > 100) { + this.errorQueue.shift(); + } + + // 尝试存储到 localStorage + try { + localStorage.setItem('errorQueue', JSON.stringify(this.errorQueue)); + } catch (e) { + console.warn('Failed to store error queue in localStorage'); + } + } + + // 手动报告错误 + reportError(error, context = {}) { + this.handleError({ + type: 'manual-report', + message: error.message, + stack: error.stack, + context: context, + timestamp: new Date().toISOString(), + userAgent: navigator.userAgent, + url: window.location.href + }); + } +} + +// 初始化错误收集器 +const errorCollector = new ErrorCollector(); + +// 导出实例供其他模块使用 +window.errorCollector = errorCollector; + +export default errorCollector + + diff --git a/ui/vhtml/vget.js b/ui/vhtml/vget.js new file mode 100644 index 0000000..b5c6df3 --- /dev/null +++ b/ui/vhtml/vget.js @@ -0,0 +1,322 @@ +/* + * vget.js + * Copyright (C) 2024 veypi + * + * Distributed under terms of the MIT license. + */ +import EventBus from './vbus.js'; +import axios from './axios.min.js' +import vcss from './vcss.js' +import vproxy from './vproxy.js'; +import vmessage from './vmessage.js' + +async function FetchFile(url) { + return fetch(url).then((response) => { + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + return response.text(); + }) +} + +var cacheUrl = {} +var pendingRequests = {}; +let baseFile = '' + +const envMap = {} +async function getEnv(scoped, temp) { + scoped = scoped || '' + if (!envMap[scoped]) { + let baseURL = scoped.startsWith('http') ? scoped : window.location.origin + scoped + envMap[scoped] = Object.assign({}, temp, { + scoped: scoped, + $G: vproxy.Wrap({}), + $bus: new EventBus(), + $axios: axios.create({ + baseURL: baseURL, + }), + $message: vmessage, + $router: null, + $emit: null, + }) + if (scoped === $vhtml.scoped || $vhtml.scoped === null) { + envMap[scoped].$router = $vhtml.$router + } else { + // 对于第三方组件,不配置路由 + envMap[scoped].$router = { addRoutes: () => { }, beforeEnter: () => { } } + } + try { + await (await import(baseURL + '/env.js')).default(envMap[scoped]) + } catch (e) { + console.warn('error loading ' + baseURL + '/env.js: ' + e) + } + } + return envMap[scoped] +} + +/** +* @param {string} url +* @return {Promise<{heads:HTMLCollection, body: HTMLElement, setup?:Element, scripts:Element[]}, scripts:Element>} +*/ +async function FetchUI(url, env, ignorescoped) { + if (!url || url === '/') { + url = '/' + } + if (!url.startsWith('http') && !url.startsWith('@')) { + if (!url.startsWith('/')) { + url = '/' + url + } + } + let scoped = env?.scoped + if (scoped && url.startsWith('/')) { + url = scoped + url + } + if (url.startsWith('@')) { + url = url.slice(1) + } + if (cacheUrl[url]) { + return Promise.resolve(cacheUrl[url]) + } + if (pendingRequests[url]) { + return pendingRequests[url]; + } + let tempenv = {} + const promise = fetch(url + "?random=" + Math.random()) + .then(async (response) => { + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + for (const [key, value] of response.headers.entries()) { + if (key.startsWith('vhtml-')) { + tempenv[key.slice(6)] = value + } + } + let scoped = tempenv.scoped || '' + if (url.startsWith('http')) { + scoped = new URL(url).origin + scoped + tempenv.scoped = scoped + } + let packEnv = await getEnv(scoped, tempenv) + Object.assign(tempenv, packEnv) + // Object.seal(tempenv) + return response.text() + }) + .then(txt => { + // if (baseFile === txt) { + // throw new Error(`HTTP error! status: 404`); + // } + if (baseFile == '') { + baseFile = txt + } + return ParseUI(txt, tempenv, url, ignorescoped) + }).then((parser) => { + cacheUrl[url] = parser + return parser + }) + .catch(err => { + let errmsg = '404' + if (err.message !== 'HTTP error! status: 404') { + console.warn(err) + } + let dom404 = document.createElement('div') + dom404.style.cssText = ` + backgound:#aaa; + height:100%; + width: 100%; + display:grid; + place-items: center; +` + dom404.innerHTML = ` +
+
404
+

${url}

+
+` + let parser = { + heads: [], + body: dom404, + setup: '', + scripts: [], + styles: '', + txt: '', + tmp: '', + env: tempenv, + err: err, + } + cacheUrl[url] = parser + return parser + }) + .finally(() => { + delete pendingRequests[url]; + }); + pendingRequests[url] = promise; + return promise; +} + +function generateCompactUniqueString() { + // 获取当前时间戳,精确到毫秒 + const timestamp = new Date().getTime(); + let shortenedTimestamp = timestamp.toString(36); + if (shortenedTimestamp.length > 4) { + shortenedTimestamp = shortenedTimestamp.substring(shortenedTimestamp.length - 4); + } + const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; + let randomPart = ''; + for (let i = 0; i < 4; i++) { + randomPart += characters.charAt(Math.floor(Math.random() * characters.length)); + } + // 组合随机部分和时间戳部分,保证总长度为8位 + return randomPart + shortenedTimestamp.padStart(4, '0'); +} + +function sync_ref_owner_id(dom, id) { + // 子组件根节点不设置data-v, 所以style class 不生效于body,只能通过body {}设置样式 + // dom.setAttribute('data-v-' + id, '') + Array.from(dom.childNodes).forEach((n) => { + if (n.nodeType === 1) { + n.setAttribute('vrefof', id) + sync_ref_owner_id(n, id) + } + }) +} + +async function ParseUI(txt, env, turl, ignorescoped) { + if (turl === undefined) { + turl = '#' + generateCompactUniqueString() + } + if (turl.endsWith('.html')) { + turl = turl.slice(0, -5) + } + let tmp = new DOMParser().parseFromString(txt, 'text/html') + if (tmp.body.hasAttribute('scoped') && !ignorescoped) { + throw new Error(`HTTP error! status: 404`); + } + let target = { + url: turl, + heads: [], + body: document.createElement('div'), + setup: undefined, + scripts: [], + styles: '', + txt: txt, + env: env, + tmp: tmp, + customAttrs: {}, + } + target.heads = Array.from(tmp.querySelector('head')?.children) + // target.heads.forEach(h => { + // }) + if (turl) { + tmp.querySelectorAll('style').forEach((s) => { + if (s.getAttribute('unscoped') === null) { + target.styles += vcss.parse(s.innerHTML, turl) + } else { + target.styles += s.innerHTML + } + }) + if (target.styles) { + const style = document.createElement('style') + style.innerHTML = target.styles + style.setAttribute('vref', turl) + document.head.appendChild(style) + } + } + target.body.append(...tmp.querySelector('body').childNodes) + // target.body = tmp.querySelector('body') + target.body.querySelectorAll('script').forEach((s) => { + let sinner = s.innerHTML.trim() + if (sinner == '') { + s.remove() + return + } + if (s.hasAttribute('setup')) { + target.setup = s + } else if (!s.hasAttribute('no-vhtml')) { + target.scripts.push(s) + } + s.remove() + }) + // target.body.classList = tmp.body.classList + Array.from(tmp.body.attributes).forEach((e) => { + if (/^[a-zA-Z]/.test(e.name)) { + target.body.setAttribute(e.name, e.value) + } else { + target.customAttrs[e.name] = e.value + } + }) + target.body.setAttribute('vref', turl) + sync_ref_owner_id(target.body, turl) + if (!ignorescoped) { + await loadHeaders(target, env) + } + return target +} + +async function loadHeaders(target, env) { + for (let h of target.heads) { + let nodeName = h.nodeName.toLowerCase() + if (nodeName === 'link') { + LoadLink(h, env) + } else if (nodeName === 'script') { + await LoadScript(h, env) + } else if (nodeName === 'title') { + target.title = h.innerText + } else { + } + } +} +/** +* @param {HTMLElement} dom +*/ +function LoadScript(dom, env) { + let src = dom.getAttribute('src') + let key = dom.getAttribute('key') + let scoped = env?.scoped + if (scoped && src.startsWith('/')) { + src = scoped + src + } + if (src.startsWith('@')) { + src = src.slice(1) + } + if (src && document.querySelector(`script[src="${src}"]`)) { + return + } + if (key && document.querySelector(`script[key="${key}"]`)) { + return + } + let newDom = document.createElement('script') + newDom.src = src + newDom.key = key + newDom.type = dom.getAttribute('type') || 'text/javascript' + return new Promise((resolve, reject) => { + newDom.onload = () => { + resolve(newDom) + }; + newDom.onerror = () => reject(new Error(`Failed to load script ${src}`)); + document.head.appendChild(newDom) + }) +} + +async function LoadLink(dom, env) { + let src = dom.getAttribute('href') + let key = dom.getAttribute('key') + let scoped = env?.scoped + if (scoped && src.startsWith('/')) { + src = scoped + src + } + if (src.startsWith('@')) { + src = src.slice(1) + } + if (src && document.querySelector(`link[href="${src}"]`)) { + return + } + if (key && document.querySelector(`link[key="${key}"]`)) { + return + } + dom.setAttribute('href', src) + document.head.append(dom) +} + + + +export default { FetchUI, FetchFile, LoadScript, LoadLink, ParseUI } diff --git a/ui/vhtml/vmessage.js b/ui/vhtml/vmessage.js new file mode 100644 index 0000000..2d2a5cf --- /dev/null +++ b/ui/vhtml/vmessage.js @@ -0,0 +1,531 @@ +/* + * vmessage.js + * Copyright (C) 2025 veypi + * + * Distributed under terms of the MIT license. + */ + +class Message { + constructor() { + this.container = null; + this.init(); + } + + /** + * 初始化容器 + */ + init() { + this.container = document.createElement('div'); + this.container.className = 'message-container'; + document.body.appendChild(this.container); + + // 添加基础样式 + this.addBaseStyles(); + } + + /** + * 添加基础样式 + */ + addBaseStyles() { + const style = document.createElement('style'); + style.textContent = ` + .message-container { + position: fixed; + top: 60px; + left: 50%; + transform: translateX(-50%); + z-index: 9999; + width: 300px; + } + + .message-item { + margin-bottom: 10px; + padding: 15px; + border-radius: 4px; + box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); + transform: translateY(100%); + opacity: 0; + transition: all 0.3s ease; + display: flex; + align-items: flex-start; + } + + .message-item.show { + transform: translateY(0); + opacity: 1; + } + + .message-icon { + margin-right: 10px; + font-size: 16px; + line-height: 1; + } + + .message-content { + flex: 1; + font-size: 14px; + line-height: 1.4; + } + + .message-close { + margin-left: 10px; + cursor: pointer; + font-size: 16px; + opacity: 0.7; + transition: opacity 0.2s; + } + + .message-close:hover { + opacity: 1; + } + + .message-success { + background-color: #f0f9eb; + border: 1px solid #e1f3d8; + color: var(--color-success, #67c23a); + } + + .message-warning { + background-color: #fdf6ec; + border: 1px solid #faecd8; + color: #e6a23c; + } + + .message-error { + background-color: #fef0f0; + border: 1px solid #fde2e2; + color: #f56c6c; + } + + .message-info { + background-color: #edf2fc; + border: 1px solid #ebeef5; + color: #409eff; + } + + .prompt-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.5); + z-index: 10000; + display: flex; + justify-content: center; + align-items: center; + opacity: 0; + transition: opacity 0.3s ease; + } + + .prompt-overlay.show { + opacity: 1; + } + + .prompt-dialog { + background: white; + border-radius: 8px; + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15); + min-width: 400px; + max-width: 500px; + transform: scale(0.8); + transition: transform 0.3s ease; + } + + .prompt-overlay.show .prompt-dialog { + transform: scale(1); + } + + .prompt-header { + padding: 20px 20px 10px; + display: flex; + justify-content: space-between; + align-items: center; + border-bottom: 1px solid #eee; + } + + .prompt-title { + font-size: 18px; + font-weight: 500; + margin: 0; + } + + .prompt-close { + cursor: pointer; + font-size: 20px; + color: #999; + border: none; + background: none; + padding: 0; + width: 20px; + height: 20px; + display: flex; + align-items: center; + justify-content: center; + } + + .prompt-close:hover { + color: #666; + } + + .prompt-body { + padding: 20px; + } + + .prompt-content { + margin-bottom: 20px; + font-size: 14px; + line-height: 1.5; + color: #333; + } + + .prompt-input { + width: 100%; + padding: 10px 12px; + border: 1px solid #dcdfe6; + border-radius: 4px; + font-size: 14px; + box-sizing: border-box; + transition: border-color 0.2s; + } + + .prompt-input:focus { + outline: none; + border-color: #409eff; + } + + .prompt-footer { + padding: 15px 20px; + text-align: right; + border-top: 1px solid #eee; + } + + .prompt-btn { + padding: 8px 16px; + border: 1px solid #dcdfe6; + border-radius: 4px; + font-size: 14px; + cursor: pointer; + margin-left: 10px; + transition: all 0.2s; + } + + .prompt-btn-cancel { + background: white; + color: #606266; + } + + .prompt-btn-cancel:hover { + background: #f5f7fa; + border-color: #c0c4cc; + } + + .prompt-btn-confirm { + background: #409eff; + color: white; + border-color: #409eff; + } + + .prompt-btn-confirm:hover { + background: #66b1ff; + border-color: #66b1ff; + } + `; + document.head.appendChild(style); + } + + /** + * 创建消息元素 + * @param {string} type - 消息类型 (success, warning, error, info) + * @param {string} content - 消息内容 + * @param {Object} options - 配置选项 + */ + createMessage(type, content, options = {}) { + const { + duration = 3000, + showClose = true, + onClose = null + } = options; + + const messageItem = document.createElement('div'); + messageItem.className = `message-item message-${type}`; + + // 消息图标 + const icons = { + success: '✓', + warning: '⚠', + error: '✕', + info: 'ℹ' + }; + + const icon = document.createElement('span'); + icon.className = 'message-icon'; + icon.textContent = icons[type] || icons.info; + + // 消息内容 + const contentEl = document.createElement('div'); + contentEl.className = 'message-content'; + contentEl.textContent = content; + + messageItem.appendChild(icon); + messageItem.appendChild(contentEl); + + // 关闭按钮 + if (showClose) { + const closeBtn = document.createElement('span'); + closeBtn.className = 'message-close'; + closeBtn.innerHTML = '×'; + closeBtn.onclick = () => { + this.removeMessage(messageItem); + if (onClose) onClose(); + }; + messageItem.appendChild(closeBtn); + } + + this.container.appendChild(messageItem); + + // 显示动画 + setTimeout(() => { + messageItem.classList.add('show'); + }, 10); + + // 自动关闭 + if (duration > 0) { + setTimeout(() => { + this.removeMessage(messageItem); + if (onClose) onClose(); + }, duration); + } + + return messageItem; + } + + /** + * 移除消息 + * @param {HTMLElement} messageItem - 消息元素 + */ + removeMessage(messageItem) { + if (messageItem && messageItem.parentNode) { + messageItem.classList.remove('show'); + setTimeout(() => { + if (messageItem.parentNode) { + messageItem.parentNode.removeChild(messageItem); + } + }, 300); + } + } + + /** + * 成功消息 + * @param {string} content - 消息内容 + * @param {Object} options - 配置选项 + */ + success(content, options = {}) { + return this.createMessage('success', content, options); + } + + /** + * 警告消息 + * @param {string} content - 消息内容 + * @param {Object} options - 配置选项 + */ + warning(content, options = {}) { + return this.createMessage('warning', content, options); + } + + /** + * 错误消息 + * @param {string} content - 消息内容 + * @param {Object} options - 配置选项 + */ + error(content, options = {}) { + return this.createMessage('error', content, options); + } + + /** + * 信息消息 + * @param {string} content - 消息内容 + * @param {Object} options - 配置选项 + */ + info(content, options = {}) { + return this.createMessage('info', content, options); + } + + /** + * 显示提示框 + * @param {string} content - 提示内容 + * @param {Object} options - 配置选项 + */ + _prompt(content, options = {}) { + return new Promise((resolve, reject) => { + const { + title = '提示', + type = 'confirm', // confirm, input + inputValue = '', + confirmText = '确定', + cancelText = '取消', + onConfirm = null, + onCancel = () => { resolve('') } + } = options; + + // 创建遮罩层 + const overlay = document.createElement('div'); + overlay.className = 'prompt-overlay'; + + // 创建对话框 + const dialog = document.createElement('div'); + dialog.className = 'prompt-dialog'; + + // 头部 + const header = document.createElement('div'); + header.className = 'prompt-header'; + + const titleEl = document.createElement('h3'); + titleEl.className = 'prompt-title'; + titleEl.textContent = title; + + const closeBtn = document.createElement('button'); + closeBtn.className = 'prompt-close'; + closeBtn.innerHTML = '×'; + + header.appendChild(titleEl); + header.appendChild(closeBtn); + + // 主体 + const body = document.createElement('div'); + body.className = 'prompt-body'; + + const contentEl = document.createElement('div'); + contentEl.className = 'prompt-content'; + contentEl.textContent = content; + + body.appendChild(contentEl); + + // 输入框(如果是input类型) + let inputEl = null; + if (type === 'input') { + inputEl = document.createElement('input'); + inputEl.className = 'prompt-input'; + inputEl.type = 'text'; + inputEl.value = inputValue; + body.appendChild(inputEl); + } + + // 底部按钮 + const footer = document.createElement('div'); + footer.className = 'prompt-footer'; + + const cancelBtn = document.createElement('button'); + cancelBtn.className = 'prompt-btn prompt-btn-cancel'; + cancelBtn.textContent = cancelText; + + const confirmBtn = document.createElement('button'); + confirmBtn.className = 'prompt-btn prompt-btn-confirm'; + confirmBtn.textContent = confirmText; + + footer.appendChild(cancelBtn); + footer.appendChild(confirmBtn); + + dialog.appendChild(header); + dialog.appendChild(body); + dialog.appendChild(footer); + overlay.appendChild(dialog); + + document.body.appendChild(overlay); + + // 显示动画 + setTimeout(() => { + overlay.classList.add('show'); + }, 10); + + // 如果是input类型,自动聚焦 + if (inputEl) { + setTimeout(() => { + inputEl.focus(); + }, 300); + } + + // 事件处理 + const closeDialog = (result = null) => { + overlay.classList.remove('show'); + setTimeout(() => { + if (overlay.parentNode) { + overlay.parentNode.removeChild(overlay); + } + }, 300); + return result; + }; + + // 关闭按钮 + closeBtn.onclick = () => { + closeDialog(); + onCancel ? onCancel() : reject(new Error('cancelled')) + }; + + // 取消按钮 + cancelBtn.onclick = () => { + closeDialog(); + onCancel ? onCancel() : reject(new Error('cancelled')) + }; + + // 确认按钮 + confirmBtn.onclick = () => { + const value = inputEl ? inputEl.value : true; + closeDialog(); + resolve(value); + if (onConfirm) onConfirm(value); + }; + + // ESC键关闭 + const handleEsc = (e) => { + if (e.key === 'Escape') { + closeDialog(); + onCancel ? onCancel() : reject(new Error('cancelled')) + document.removeEventListener('keydown', handleEsc); + } + }; + + document.addEventListener('keydown', handleEsc); + + // 点击遮罩层关闭 + overlay.onclick = (e) => { + if (e.target === overlay) { + closeDialog(); + onCancel ? onCancel() : reject(new Error('cancelled')) + } + }; + }); + } + + /** + * 确认框 + * @param {string} content - 确认内容 + * @param {Object} options - 配置选项 + */ + confirm(content, options = {}) { + return this._prompt(content, { + ...options, + type: 'confirm' + }); + } + + /** + * 输入框 + * @param {string} content - 提示内容 + * @param {Object} options - 配置选项 + */ + prompt(message, content, options = {}) { + return this._prompt(message, { + ...options, + type: 'input', + inputValue: content, + }); + } +} + +// 创建单例实例 +const message = new Message(); + +// 导出默认实例和类 +export default message; +export { Message }; diff --git a/ui/vhtml/vproxy.js b/ui/vhtml/vproxy.js new file mode 100644 index 0000000..0a35ba6 --- /dev/null +++ b/ui/vhtml/vproxy.js @@ -0,0 +1,553 @@ +/* + * proxy.js + * Copyright (C) 2024 veypi + * + * Distributed under terms of the MIT license. + */ + + +/** @type {([boolean, ()=>void])[]} */ +const callbackList = [] +/** @type {number[]} */ +const cacheUpdateList = [] +// 界面更新响应频率40hz +const sync = () => { + let list = new Set(cacheUpdateList.splice(0)) + let c = 0 + for (let l of list) { + if (callbackList[l]) { + callbackList[l]() + c++ + } + } + if (c > 0) { + console.log(`update ${c}`) + // sync() + } + return c +} +setInterval(sync, 25) + +function GenUniqueID() { + const timestamp = performance.now().toString(36); + const random = Math.random().toString(36).substring(2, 5); + return `${timestamp}-${random}`; +} + +function ForceUpdate() { + for (let c of callbackList) { + if (c) { + c() + } + } +} + +window.$vupdate = (id) => { + console.log('update', id) + callbackList[id]() +} + +function deepAccess(obj, seen = new Set()) { + if (obj && typeof obj === 'object' && !seen.has(obj)) { + seen.add(obj) + for (let key in obj) { + deepAccess(obj[key], seen) + } + } + return obj +} + +/** @type {number[]} */ +var listen_tags = [] +/** +* @param {()=>void} callback +* @returns number +*/ +function Watch(target, callback, options) { + let idx = callbackList.length + listen_tags.push(idx) + if (typeof callback === 'function') { + callbackList.push(() => { + callback(target()) + }) + } else { + callbackList.push(target) + } + let res + try { + res = target() + if (options && options.deep) { + deepAccess(res) + } + } catch (e) { + console.warn('running \n%s\n failed:', target, e) + } finally { + listen_tags.pop() + } + if (typeof callback === 'function') { + callback(res) + } + return idx +} + +function Cancel(idx) { + if (idx < 0 || idx >= callbackList.length) { + return + } + callbackList[idx] = null +} + +const isProxy = Symbol("isProxy") +const DataID = Symbol("DataID") +const DataBind = Symbol("bind") +const rootObj = Symbol("root") +const rootArg = Symbol("root arg") + + +function SetDataRoot(data, root) { + data[rootObj] = root + Object.keys(root).forEach(k => { + if (k in data) { + } else { + data[k] = rootArg + } + }) +} + +function isProxyType(v) { + if (!v || typeof v !== 'object') { + return false + } + if (v instanceof Node || v instanceof Date || v instanceof RegExp || v instanceof Event) { + return false + } + if (v.__noproxy) { + return false + } + if (v.constructor !== Object && v.constructor !== Array) { + return false + } + return true +} + +// oldValue只集成值, 不继承事件 +function copyBind(oldValue, newValue) { + if (!oldValue || !oldValue[isProxy] || !isProxyType(newValue)) { + return newValue + } + let binds = oldValue[DataBind] + if (newValue[isProxy]) { + // 新值也是代理对象,继承旧值的事件绑定, 使用新的代理对象 + if (newValue[DataID] === oldValue[DataID]) { + return newValue + } + for (let k in binds) { + if (newValue[DataBind][k]?.indexOf) { + const currentBinds = newValue[DataBind][k] + const bindSet = new Set(currentBinds) + for (let i of binds[k]) { + if (!bindSet.has(i)) { + currentBinds.push(i) + bindSet.add(i) + } + } + } else { + newValue[DataBind][k] = binds[k] + } + } + } else { + // 新值不是代理对象,继承值,使用旧的代理对象 + if (Array.isArray(newValue) && Array.isArray(oldValue)) { + oldValue.length = 0 + for (let i = 0; i < newValue.length; i++) { + oldValue.push(newValue[i]) + } + return oldValue + } + Object.keys(oldValue).forEach(k => { + if (!newValue.hasOwnProperty(k)) { + delete oldValue[k] + } + }) + Object.keys(newValue).forEach(k => { + if (oldValue[k]?.[isProxy]) { + oldValue[k] = copyBind(oldValue[k], newValue[k]) + } else { + oldValue[k] = newValue[k] + } + }) + return oldValue + } + for (let k in newValue) { + if (k in oldValue && oldValue[k]?.[isProxy]) { + newValue[k] = copyBind(oldValue[k], newValue[k]) + } + } + return newValue +} + + +let stopChecking = false +function Wrap(data, root = undefined) { + const did = GenUniqueID() + let isArray = false + if (Object.prototype.toString.call(data) === '[object Array]') { + isArray = true + } + if (root) { + SetDataRoot(data, root) + } + // data[DataID] = did + const listeners = {} + const handler = { + /** + * @param {Object} target + * @param {string|symbol} key + * + * */ + get(target, key, receiver) { + if (key === DataID) { + return did + } else if (key === isProxy) { + return true + } else if (key === DataBind) { + return listeners + } + const value = Reflect.get(target, key, receiver) + if (value === rootArg) { + return target[rootObj][key] + } + if (typeof key === 'symbol' && stopChecking) { + return value + } else if (typeof value === 'function') { + return value + } + let idx = -1 + if (listen_tags.length > 0) { + let lkey = key + idx = listen_tags[listen_tags.length - 1] + if (isArray) { + lkey = '' + } + if (!listeners.hasOwnProperty(lkey)) { + listeners[lkey] = [idx] + } else if (listeners[lkey].indexOf(idx) == -1) { + listeners[lkey].push(idx) + } + } + if (window.vdev) { + console.log(`${did} get ${key.toString()}:|${value}| `) + } + if (isProxyType(value) && !value[isProxy]) { + let newValue = Wrap(value, undefined) + Reflect.set(target, key, newValue, receiver) + return newValue + } + return value; + }, + set(target, key, newValue, receiver) { + const oldValue = Reflect.get(target, key, receiver) + if (oldValue === rootArg) { + target[rootObj][key] = newValue + return true + } + if (oldValue === newValue) { + return true + } else if (stopChecking) { + return Reflect.set(target, key, newValue, receiver) + } + let result = true + if (Array.isArray(newValue) && Array.isArray(oldValue)) { + stopChecking = true + oldValue.length = 0 + for (let i = 0; i < newValue.length; i++) { + oldValue.push(newValue[i]) + } + stopChecking = false + } else if (oldValue && oldValue[isProxy] && isProxyType(newValue)) { + // 监听对象只赋值可迭代属性 + newValue = copyBind(oldValue, newValue) + result = Reflect.set(target, key, newValue, receiver); + } else { + result = Reflect.set(target, key, newValue, receiver); + } + if (result && listen_tags.length === 0) { + let lkey = key + if (isArray) { + lkey = '' + } + if (listeners[lkey]) { + let i = 0 + if (window.vdev) { + console.log(`before set ${key} listeners:`, listeners[lkey], target) + } + while (i < listeners[lkey].length) { + let cb = listeners[lkey][i] + if (!callbackList[cb]) { + listeners[lkey].splice(i, 1); + } else { + i++ + if (window.vdev) { + console.log(`${did} set ${key}:`, '\n', callbackList[cb], '\n', oldValue, newValue) + } + cacheUpdateList.push(cb) + } + } + } + } + return result; + }, + deleteProperty(target, key) { + if (window.vdev) { + console.log(`del ${key}`) + } + const result = Reflect.deleteProperty(target, key); + if (result && listen_tags.length === 0) { + let lkey = key + if (isArray) { + lkey = '' + } + if (listeners[lkey]) { + let i = 0 + while (i < listeners[lkey].length) { + let cb = listeners[lkey][i] + if (!callbackList[cb]) { + listeners[lkey].splice(i, 1); + } else { + i++ + cacheUpdateList.push(cb) + if (window.vdev) { + console.log(`${did} del ${key}:`, '\n', callbackList[cb], '\n') + } + } + } + } + } + return result + }, + }; + + let res = new Proxy(data, handler); + return res +} + +const expose = { + 'console': console, + 'window': window, + 'prompt': prompt.bind(window), + 'alert': alert.bind(window), + 'confirm': confirm.bind(window), + 'RegExp': RegExp, + 'document': document, + 'Array': Array, + 'Object': Object, + 'Math': Math, + 'Date': Date, + 'JSON': JSON, + 'Symbol': Symbol, + 'Number': Number, + 'eval': eval, + 'isNaN': isNaN, + 'parseInt': parseInt, + 'parseFloat': parseFloat, + 'setTimeout': setTimeout.bind(window), + 'setInterval': setInterval.bind(window), + 'clearTimeout': clearTimeout.bind(window), + 'clearInterval': clearInterval.bind(window), + 'encodeURIComponent': encodeURIComponent, + 'btoa': btoa.bind(window), + 'fetch': fetch.bind(window), + 'TextDecoder': TextDecoder, + 'history': history, + 'requestAnimationFrame': requestAnimationFrame.bind(window), +} + +function newProxy(data, env, tmpenv) { + const proxy = new Proxy(data, { + // 拦截所有属性,防止到 Proxy 对象以外的作用域链查找。 + has(target, key) { + return true; + }, + get(target, key, receiver) { + let v + if (key === '$data') { + v = data + } else if (key === '$env') { + v = env + } else if (key in target) { + v = Reflect.get(target, key, receiver); + } else if (key in env) { + v = env[key] + } else if (tmpenv && key in tmpenv) { + v = tmpenv[key] + } else if (key in expose) { + v = expose[key] + } else if (key in window) { + v = window[key] + } + return v + }, + set(target, key, newValue, receiver) { + // code global variable set will work on "data" + return Reflect.set(target, key, newValue, receiver); + } + }); + return proxy +} +// 运行dom属性绑定等小代码语句 +// for code snapshot +function Run(originCode, data, env, tmpenv) { + let code = originCode.trim() + const cleanCode = code.replace(/\/\*[\s\S]*?\*\/|\/\/.*/g, '').trim() + const isStatement = /^(var|let|const|if|for|while|switch|try|throw|class|function|return|debugger)\b/.test(cleanCode) + if (!isStatement && (code.indexOf('\n') === -1 || !cleanCode.includes(';'))) { + code = 'return ' + code + } + code = ` +with (sandbox) { +${code} +}` + let res + try { + const fn = new Function('sandbox', code); + res = fn(newProxy(data, env, tmpenv)) + } catch (error) { + console.warn(`Run error:`, originCode, '\n', error) + } + return res +} + +const AsyncFunction = Object.getPrototypeOf(async function() { }).constructor + +// 运行大段代码库 +async function AsyncRun(originCode, data, env, tmpenv) { + let code = originCode.trim() + if (code.indexOf('\n') === -1) { + code = 'return ' + code + } + code = ` +with (sandbox) { +${code} +}` + // try { + const fn = new AsyncFunction('sandbox', code); + return await fn(newProxy(data, env, tmpenv)) + // } catch (error) { + // console.warn('AsyncRun error:', error, '\n', originCode) + // } +} + +function resolvePath(relativePath, currentPath) { + // 如果相对路径已经是绝对路径,直接返回 + if (relativePath.startsWith('/')) { + return relativePath; + } + + // 获取当前路径的目录部分(去掉文件名) + const currentDir = currentPath.substring(0, currentPath.lastIndexOf('/')); + + // 分割路径段 + const currentSegments = currentDir.split('/').filter(segment => segment !== ''); + const relativeSegments = relativePath.split('/').filter(segment => segment !== ''); + + // 处理相对路径段 + for (const segment of relativeSegments) { + if (segment === '..') { + // 返回上一级目录 + if (currentSegments.length > 0) { + currentSegments.pop(); + } + } else if (segment === '.') { + // 当前目录,不做任何操作 + continue; + } else { + // 普通目录或文件名 + currentSegments.push(segment); + } + } + + // 构建绝对路径 + return '/' + currentSegments.join('/'); +} + + +async function ParseImport(code, data, env, src) { + data = data || {} + let scoped = env.scoped || '' + let codeCopy = code + let match; + src = src.startsWith('http') ? src : scoped + src + + const awaitImportRegex = /await import\(['"]([^'"]+)['"]\)/gm; + while ((match = awaitImportRegex.exec(code)) !== null) { + let url = match[1] + if (!url.startsWith('http')) { + url = resolvePath(url, src) + url = window.location.origin + url + } + codeCopy = codeCopy.replace(match[0], `await import('${url}')`) + } + + const importRegex = /^[\s/]*import\s+([\w{},\s]+)\s+from\s+['"]([^'"]+)['"][;\s]*$/gm; + + // 提取所有匹配的模块路径 + while ((match = importRegex.exec(code)) !== null) { + codeCopy = codeCopy.replace(match[0], '') + if (match[0].trim().startsWith('//')) { + continue + } + let url = match[2] + if (!url.startsWith('http') && !url.startsWith('@')) { + if (url.startsWith('/') && scoped) { + url = scoped + url + } else { + url = resolvePath(url, src) + } + } + if (url.startsWith('@')) { + url = url.slice(1) + } + if (!url.endsWith('.js')) { + url += '.js' + } + if (!url.startsWith('http')) { + url = window.location.origin + url + } + let packname = match[1].trim() + try { + let packs = null + if (/^\w+$/.test(packname)) { + packs = packname + } else if (/^{[\w\s,]+}$/.test(packname)) { + packs = packname.slice(1, -1).split(',').map(p => p.trim()) + } else { + throw new Error('unsupported import: ' + match[0]) + } + // window.$env = env + const module = await import(url) + if (typeof packs === 'string') { + if (module.default) { + data[packs] = module.default + } else { + data[packs] = module + } + } else { + packs.forEach((p) => { + if (p in module) { + data[p] = module[p] + } else if (p in module.default) { + data[p] = module.default[p] + } + }) + } + } catch (error) { + console.error(`模块加载失败 (${match[0]}):`, error.message); + } + } + return codeCopy.trim() +} + +export default { + Wrap, Watch, Cancel, ForceUpdate, SetDataRoot, + DataID, GenUniqueID, Run, AsyncRun, ParseImport +} diff --git a/ui/vhtml/vrouter.js b/ui/vhtml/vrouter.js new file mode 100644 index 0000000..c331276 --- /dev/null +++ b/ui/vhtml/vrouter.js @@ -0,0 +1,624 @@ +import vproxy from './vproxy.js' +import vget from './vget.js' + +// 解析URL字符串,提取路径、查询参数和hash +function parseUrlString(urlString, scoped) { + let url + + let path + // 判断是否为完整URL(包含协议) + if (urlString.startsWith('http://') || urlString.startsWith('https://')) { + url = new URL(urlString) + // 如果是外部URL,返回null(不处理外部链接) + if (url.origin !== window.location.origin) { + return null + } + if (url.pathname.startsWith(scoped)) { + path = url.pathname.slice(scoped.length) // 去掉根路径 + } + } else { + // 相对路径,基于当前origin构建完整URL + url = new URL(urlString, window.location.href) + path = url.pathname + } + + // 解析查询参数 + const query = {} + url.searchParams.forEach((value, key) => { + query[key] = value + }) + + return { + path: path, + query, + hash: url.hash + } +} + + +class VRouter { + #routes = [] + #history = [] + #current = null + #scoped = '' + #listeners = [] + #pageCache = new Map() + #node = null + #env = null + #originContent = [] + #loaded = false + #vhtml = null + #routesByName = new Map() // 添加按名称索引的路由缓存 + + constructor() { + this.init() + } + + get routes() { return this.#routes.slice() } + get history() { return this.#history.slice() } + get current() { return this.#current } + get query() { return this.#current?.query || {} } + get params() { return this.#current?.params || {} } + get scoped() { return this.#scoped } + + onChange(fc) { + this.#listeners.push(fc) + } + + addRoute(route) { + if (!route.path) throw new Error('Route must have a path') + if (route.path != '/' && route.path.endsWith('/')) { + route.path = route.path.slice(0, -1) + } + + const routeConfig = { + path: route.path, + component: route.component, + name: route.name, + meta: route.meta || {}, + children: route.children || [], + matcher: new RouteMatcher(route.path, route.name), + description: route.description || '', + layout: route.layout || '', + } + + this.#routes.push(routeConfig) + + // 如果有名称,添加到名称索引中 + if (route.name) { + this.#routesByName.set(route.name, routeConfig) + } + + // 递归处理子路由 + if (route.children?.length > 0) { + route.children.forEach(child => { + const childPath = route.path + (child.path.startsWith('/') ? child.path : '/' + child.path) + const layout = child.layout || route.layout || '' + const meta = { ...route.meta, ...child.meta } + this.addRoute({ ...child, path: childPath, parent: routeConfig, layout, meta }) + }) + } + } + + addRoutes(routes) { + routes.forEach(route => this.addRoute(route)) + } + + #notifyListeners(to, from) { + this.#listeners.forEach(listener => { + if (typeof listener === 'function') { + try { + listener(to, from) + } catch (error) { + console.error('Error in router listener:', error) + } + } + }) + } + + #setRouterPath(matchedRoute) { + const oldRoute = this.#current + + this.#current = { + path: matchedRoute.path, + fullPath: matchedRoute.fullPath, + params: matchedRoute.params || {}, + query: matchedRoute.query || {}, + hash: new URL(matchedRoute.fullPath, window.location.origin).hash, + meta: matchedRoute.route?.meta || {}, + description: matchedRoute.route?.description || '', + layout: matchedRoute.route?.layout || '', + name: matchedRoute.route?.name, + matched: matchedRoute.route ? [matchedRoute.route] : [] + } + + this.#history.push(this.#current) + if (this.#scoped && !matchedRoute.fullPath.startsWith('http')) { + history.pushState({}, '', this.#scoped + matchedRoute.fullPath) + } else { + history.pushState({}, '', matchedRoute.fullPath) + } + this.#notifyListeners(this.#current, oldRoute) + } + + // 优化后的路由匹配方法,支持多种参数类型 + matchRoute(to) { + // 处理不同类型的路由参数 + const routeInfo = this.normalizeRouteTarget(to) + if (!routeInfo) return null + + const { path, query, params, name } = routeInfo + + // 如果是按名称匹配 + if (name) { + const route = this.#routesByName.get(name) + if (!route) return null + + // 构建带参数的路径 + let resolvedPath = route.path + Object.entries(params).forEach(([key, value]) => { + resolvedPath = resolvedPath.replace(`:${key}`, value) + }) + + const match = route.matcher.match(resolvedPath) + if (match) { + return { + route, + params: { ...match.params, ...params }, + matched: match.matched, + path: resolvedPath, + query, + name + } + } + return null + } + + // 按路径匹配 + for (const route of this.#routes) { + const match = route.matcher.match(path) + if (match && route.component) { + return { + route, + params: { ...match.params, ...params }, + matched: match.matched, + description: route.description, + layout: route.layout, + path, + query, + name: route.name + } + } + } + return null + } + + // 标准化路由目标参数 + normalizeRouteTarget(to) { + let path, query = {}, params = {}, hash = '', name + + if (typeof to === 'string') { + // 字符串类型:解析可能包含的URL、query、hash + const parsed = parseUrlString(to, this.#scoped) + if (!parsed) return null // 外部URL或解析失败 + + path = parsed.path + query = { ...parsed.query } + hash = parsed.hash + } else if (to && typeof to === 'object') { + if (to.path) { + // {path} 类型:path可能也包含query和hash + const parsed = parseUrlString(to.path, this.#scoped) + if (!parsed) return null + + path = parsed.path + // 合并query参数,对象中的query优先级更高 + query = { ...parsed.query, ...(to.query || {}) } + hash = to.hash || parsed.hash + params = to.params || {} + } else if (to.name) { + // {name} 类型 + name = to.name + query = to.query || {} + params = to.params || {} + hash = to.hash || '' + } else { + return null + } + } else { + return null + } + + // 标准化路径 + if (path && !path.startsWith('/')) { + path = '/' + path + } + if (this.#scoped) { + path = path.startsWith(this.#scoped) ? path.slice(this.#scoped.length) : path + } + + if (!path.startsWith('/')) { + path = '/' + path + } + + if (path != '/' && path.endsWith('/')) { + path = path.slice(0, -1) + } + + return { path, query, params, hash, name } + } + + matchTo(to) { + const matchResult = this.matchRoute(to) + if (!matchResult) return null + + const { route, params, query, path, name } = matchResult + + // 构建查询字符串 + let search = '' + if (query && Object.keys(query).length > 0) { + search = '?' + Object.entries(query) + .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`) + .join('&') + } + + const fullPath = (path || matchResult.path) + search + + return { + route, + params, + query, + name: name || route.name, + path: path || matchResult.path, + fullPath, + matched: [route] + } + } + + buildUrl(baseUrl, additionalQuery = {}) { + const url = new URL(baseUrl, window.location.origin) + Object.entries(additionalQuery).forEach(([key, value]) => { + url.searchParams.append(key, value) + }) + return url + } + + resolveRoutePath(route, params = {}) { + let path = route.component || route.path + + Object.entries(params).forEach(([key, value]) => { + path = path.replace(`:${key}`, value) + }) + + if (path === '/' || path === '') path = '/index' + if (!path.startsWith('/')) path = '/' + path + if (path.endsWith('.html')) path = path.slice(0, -5) + if (path.endsWith('/')) path = path.slice(0, -1) + + return path + } + + async #navigateTo(matchedRoute) { + if (!matchedRoute) { + console.warn(`No route matched`) + return + } + + const { route, params, query } = matchedRoute + + const to = { + path: matchedRoute.path, + fullPath: matchedRoute.fullPath, + params, + query, + hash: new URL(matchedRoute.fullPath, window.location.origin).hash, + meta: route.meta, + description: route.description, + layout: route.layout, + name: route.name, + matched: [route] + } + + if (this.beforeEnter) { + try { + let shouldContinue = true + const result = await this.beforeEnter(to, this.#current, (next) => { + if (next) { + shouldContinue = false + this.push(next) + } + }) + if (result === false || !shouldContinue) return + } catch (error) { + console.error('Error in beforeEnter guard:', error) + return + } + } + + const cacheKey = matchedRoute.fullPath + let page = this.#pageCache.get(cacheKey) + + this.#setRouterPath(matchedRoute) + if (page) { + page.activate() + } else { + page = new Page(this.#vhtml, this.#node, matchedRoute) + await page.mount(this.#env, this.#originContent, to.layout) + this.#pageCache.set(cacheKey, page) + } + + } + + async push(to) { + const matchedRoute = this.matchTo(to) + + if (!matchedRoute) { + const target = typeof to === 'string' ? to : (to.path || `name: ${to.name}`) + console.warn(`No route matched for ${target}`) + return + } + + await this.#navigateTo(matchedRoute) + } + + replace(to) { + this.push(to) + if (this.#history.length > 1) { + this.#history.splice(-2, 1) + } + } + + go(n) { history.go(n) } + back() { history.back() } + forward() { history.forward() } + + init() { + if (this.#loaded) return + this.#loaded = true + + document.body.addEventListener('click', (event) => { + const linkElement = event.target.closest('a') + if (!linkElement) return + + const href = linkElement.getAttribute('href') + if (!href || href.startsWith('http') || href.startsWith('#')) return + + + event.preventDefault() + const reload = linkElement.hasAttribute('reload') + if (reload) { + window.location.href = href + } else { + this.push(href) + } + }, true) + + window.addEventListener('popstate', () => { + this.push(window.location.href) + }) + } + + ParseVrouter($vhtml, $node, env) { + this.#node = $node + this.#env = env + this.#scoped = env.scoped || '' + this.#originContent = Array.from($node.childNodes) + this.#vhtml = $vhtml + this.push(window.location.href) + } +} + +// 优化后的路由匹配器 +class RouteMatcher { + constructor(path, name) { + this.originalPath = path + this.name = name + this.keys = [] + this.regexp = this.pathToRegexp(path) + } + + pathToRegexp(path) { + const paramPattern = /:([^(/]+)/g + let regexpStr = path.replace(paramPattern, (match, key) => { + this.keys.push(key) + return `(?<${key}>[^/]+)` + }) + + // 处理 *path 形式的通配符 + regexpStr = regexpStr.replace(/\*(\w+)/g, (match, key) => { + this.keys.push(key) + return `(?<${key}>.*)` + }); + + // 如果有未处理的*号,将其替换为允许匹配任意数量字符的正则表达式 + regexpStr = regexpStr.replace(/\*/g, '.*') + return new RegExp(`^${regexpStr}$`) + } + + // 优化的匹配方法,支持多种参数类型 + match(target) { + let path + + // 处理不同类型的输入 + if (typeof target === 'string') { + path = target + } else if (target && typeof target === 'object') { + if (target.path) { + path = target.path + } else if (target.name && target.name === this.name) { + // 如果按名称匹配且名称相符,返回基本匹配 + return { + path: this.originalPath, + params: target.params || {}, + matched: this.originalPath + } + } else { + return null + } + } else { + return null + } + + const match = this.regexp.exec(path) + if (!match) return null + + const params = {} + this.keys.forEach(key => { + if (match.groups?.[key]) { + params[key] = match.groups[key] + } + }) + + return { + path: this.originalPath, + params, + matched: match[0] + } + } +} + +const layoutCache = new Map() + +class Page { + constructor(vhtml, node, matchedRoute) { + this.vhtml = vhtml + this.node = node + this.layoutDom = undefined + this.matchedRoute = matchedRoute + this.htmlPath = this.resolveHtmlPath(matchedRoute) + } + + resolveHtmlPath(matchedRoute) { + let path = matchedRoute.route.component || matchedRoute.route.path + if (typeof path === 'function') { + path = path(matchedRoute.path) + } + + Object.entries(matchedRoute.params).forEach(([key, value]) => { + path = path.replace(`:${key}`, value) + }) + + if (!path.startsWith('/')) path = '/' + path + if (path.endsWith('/')) path = path.slice(0, -1) + if (!path.endsWith('.html')) path = path + '.html' + + return path + } + + async mount(env, originContent, layout) { + + const parser = await vget.FetchUI(this.htmlPath, env) + if (parser.err) { + console.warn(parser.err) + let dom = document.createElement('div') + Object.assign(dom.style, { width: '100%', height: '100%' }) + dom.append(...originContent) + this.node.innerHTML = '' + this.node.append(dom) + this.vhtml.parseRef(this.htmlPath, dom, {}, env, null, true) + return + } + this.title = parser.title || '' + + + const slots = {} + const dom = document.createElement("div") + dom.setAttribute('vsrc', this.htmlPath) + slots[''] = [dom] + this.slots = slots + + if (!layout) { + this.node.innerHTML = '' + this.node.append(dom) + this.vhtml.parseRef(this.htmlPath, dom, {}, env, null) + return + } + + let layoutDom = layoutCache.get(layout) + if (!layoutDom) { + let layoutUrl = layout + if (!layoutUrl.startsWith('/')) { + layoutUrl = '/' + layout + } + if (!layoutUrl.endsWith('.html')) { + layoutUrl += '.html' + } + if (!layoutUrl.startsWith('/layout')) { + layoutUrl = '/layout' + layoutUrl + } + const layoutParser = await vget.FetchUI(layoutUrl, env) + if (layoutParser.err) { + console.warn(`get layout ${layoutUrl} failed.`, layoutParser.err) + this.node.innerHTML = '' + this.node.append(dom) + this.vhtml.parseRef(this.htmlPath, dom, {}, env, null) + return + } + layoutDom = layoutParser.body.cloneNode(true) + layoutCache.set(layout, layoutDom) + dom.$refData = vproxy.Wrap({}) + layoutDom.$refSlots = vproxy.Wrap({ ...slots }) + this.node.innerHTML = '' + this.node.append(layoutDom) + this.layoutDom = layoutDom + this.vhtml.parseRef('/layout/' + layout, layoutDom, {}, env, null, true) + } else { + + this.layoutDom = layoutDom + this.activate() + } + } + + activate() { + if (this.title) document.title = this.title + const layoutDom = this.layoutDom + + if (layoutDom) { + layoutDom.querySelectorAll("vslot").forEach(e => { + if (e.closest('[vref]') === layoutDom && this.slots[e.getAttribute('name') || '']) { + e.innerHTML = '' + } + }) + Object.keys(layoutDom.$refSlots).forEach(key => { + delete layoutDom.$refSlots[key] + }) + Object.assign(layoutDom.$refSlots, this.slots) + if (!layoutDom.isConnected) { + this.node.innerHTML = '' + } + this.node.append(layoutDom) + } else { + this.node.innerHTML = '' + const dom = this.slots[''] + if (dom instanceof Array) { + this.node.append(...dom) + } else { + this.node.append(dom) + } + } + } +} + +const $router = new VRouter() + +const DefaultRoutes = [ + { + path: '/', + component: '/page/index.html', + name: 'home', + }, + { + path: '/404', + component: '/page/404.html', + name: '404' + }, + { + path: '*', + component: (path) => { + if (path.endsWith('.html')) return path + return '/page' + path + '.html' + }, + } +] + +export default { $router, DefaultRoutes }