@joker.front/cli
Version:
The Next-Generation Front-End Toolchain: Swift, Efficient, and Adaptive.
2 lines (1 loc) • 9.32 kB
JavaScript
var e;!function(e){function t(e,t){let n=`[JOKERCLI]: ${t}`;console[e](n)}e.info=function(e){t("info",e)},e.warn=function(e){t("warn",e)},e.error=function(e,n){t("error",e),n&&console.error(n)}}(e||(e={}));const t="joker-error-overlay",n=/(?:[a-zA-Z]:\\|\/).*?:\d+:\d+/g,a=/^(?:>?\s+\d+\s+\|.*|\s+\|\s*\^.*)\r?\n/gm;class s extends HTMLElement{root;constructor(e){super(),this.root=this.attachShadow({mode:"open"}),this.root.innerHTML='\n<style>\n:host {\n position: fixed;\n top: 0;\n left: 0;\n z-index: 99999;\n width: 100%;\n height: 100%;\n overflow-y: scroll;\n margin: 0;\n background: rgba(0, 0, 0, 0.66);\n\n --font: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier;\n --red: #ff5555;\n --yellow: #e2aa53;\n --purple: #cfa4ff;\n --cyan: #2dd9da;\n --dim: #c9c9c9;\n}\n\n.window {\n font-family: var(--font);\n line-height: 1.5;\n color: #d8d8d8;\n margin: 30px 0;\n padding: 25px 40px;\n position: relative;\n background: #181818;\n border-radius: 6px 6px 8px 8px;\n box-shadow: 0 19px 38px rgba(0, 0, 0, 0.3), 0 15px 12px rgba(0, 0, 0, 0.22);\n overflow: hidden;\n border-top: 8px solid var(--red);\n direction: ltr;\n text-align: left;\n}\n\npre {\n font-family: var(--font);\n font-size: 16px;\n margin-top: 0;\n margin-bottom: 1em;\n overflow-x: scroll;\n scrollbar-width: none;\n}\n\npre::-webkit-scrollbar {\n display: none;\n}\n\n.message {\n line-height: 1.3;\n font-weight: 600;\n white-space: pre-wrap;\n}\n\n.message-body {\n color: var(--red);\n}\n\n.plugin {\n color: var(--purple);\n}\n\n.file {\n color: var(--cyan);\n margin-bottom: 0;\n white-space: pre-wrap;\n word-break: break-all;\n}\n\n.frame {\n color: var(--yellow);\n}\n\n.stack {\n font-size: 13px;\n color: var(--dim);\n}\n\n.tip {\n font-size: 13px;\n color: #999;\n border-top: 1px dotted #999;\n padding-top: 13px;\n}\n\n.file-link {\n text-decoration: underline;\n cursor: pointer;\n}\n</style>\n<div class="window">\n <pre class="message">\n <span class="plugin"></span>\n <span class="message-body"></span>\n </pre>\n <pre class="file"></pre>\n <pre class="frame"></pre>\n <pre class="stack"></pre>\n <div class="tip">点击空白处关闭该遮罩提示</div>\n</div>\n',a.lastIndex=0;let t=e.frame&&a.test(e.frame),n=t?e.message.replace(a,""):e.message;e.plugin&&this.text(".plugin",`[插件:${e.plugin}]`),this.text(".message-body",n.trim());let[s]=(e.loc?.file||e.id||"未知文件").split("?");e.loc?this.text(".file",`${s}:${e.loc.line}:${e.loc.column}`,!0):e.id&&this.text(".file",s),t&&this.text(".frame",e.frame.trim()),this.text(".stack",e.stack,!0),this.root.querySelector(".window")?.addEventListener("click",(e=>{e.stopPropagation()})),this.addEventListener("click",(()=>{this.close()}))}text(e,t,a=!1){let s=this.root.querySelector(e);if(!1===a)return void(s.textContent=t);let i,o=0;for(;i=n.exec(t);){let{0:e,index:n}=i;if(null!==n){let a=t.slice(o,n);s.appendChild(document.createTextNode(a));let i=document.createElement("a");i.textContent=e,i.className="file-link",i.onclick=()=>{fetch(`/__open-in-editor?file=${encodeURIComponent(e)}`)},s.appendChild(i),o+=a.length+e.length}}}close(){this.parentNode?.removeChild(this)}}function i(){document.querySelectorAll(t).forEach((e=>{e.close()}))}function o(e){i(),document.body.appendChild(new s(e))}void 0===customElements.get(t)&&customElements.define(t,s);let r=new URL(import.meta.url),l="https"===location.protocol?"wss":"ws",c=__BASE__,d=__HMR_PORT__,p=__HMR_CLIENT_ID__,h=`${__HMR_HOSTNAME__||r.hostname}:${d||r.port}${c}`;async function u(e){await new Promise((t=>setTimeout(t,e)))}let f=new class{socket;isOpened=!1;messageQueue=new Set;listeners=new Map;isUpdated=!1;pruneMap=new Map;urlDataMap=new Map;hotModuleMap=new Map;depExecMap=new Map;constructor(){if(d){try{this.socket=new WebSocket(`${l}://${h}`,"joker-hmr")}catch(t){e.error("WebSocket connection failed")}this.initEventListener()}else e.warn("HMR is disabled. Applying fallback mode with feature degradation compensation only")}initEventListener(){this.socket?.addEventListener("open",(()=>{this.isOpened=!0}),{once:!0}),this.socket?.addEventListener("message",(async({data:e})=>{this.receiveMessage(JSON.parse(e))})),this.socket?.addEventListener("close",(async({wasClean:t})=>{t||(e.info("Connection to server lost. Attempting to reconnect..."),await this.waitingToConnect(),location.reload())}))}receiveMessage(n){if(n.clientId===p)switch(n.type){case"connected":e.info("Server connection established"),this.sendMessages(),setInterval((()=>{this.socket?.send("{'type':'ping'}")}),__HMR_HEARTTIMER__);break;case"update":if(this.notify("before:update",n),!1===this.isUpdated&&0!==document.querySelectorAll(t).length)return void window.location.reload();i(),this.isUpdated=!0,n.updates.forEach((e=>{"css-update"===e.type?this.updateCss(e):this.updateScript(e)}));break;case"custom":this.notify(n.event,n.data);break;case"reload":if(this.notify("before:reload",n),n.path?.endsWith(".html")){let e=decodeURI(location.pathname),t=c+n.path.slice(1);(e===t||"/index.html"===n.path||e.endsWith("/")&&e+"index.html"===t)&&location.reload()}else location.reload();break;case"prune":this.notify("before:prune",n),n.paths.forEach((e=>{this.pruneMap.get(e)?.(this.urlDataMap.get(e))}));break;case"error":this.notify("error",n),e.error(`Error detected:\n${n.err.message}\n${n.err.stack}`),o(n.err);break;default:e.warn("Unknown HMR type detected. This might be caused by version mismatch between CLI and client")}}async waitingToConnect(){let e="wss"===l?"https":"http";for(;;)try{await fetch(`${e}://${h}`,{mode:"no-cors"});break}catch(e){await u(1500)}}sendMessages(){1===this.socket?.readyState&&(this.messageQueue.forEach((e=>{this.socket?.send(e)})),this.messageQueue.clear())}notify(e,t){let n=this.listeners.get(e);n&&n.forEach((e=>e(t)))}updateCss(t){let n=this.clearnUrl(t.path),a=Array.from(document.querySelectorAll("link")).find((e=>this.clearnUrl(e.href).includes(n)));if(a){let s=`${c}${n.slice(1)}${n.includes("?")?"&":"?"}t=${t.timestamp}`,i=a.cloneNode();i.href=new URL(s,a.href).href,i.addEventListener("load",(()=>a?.remove())),i.addEventListener("error",(()=>a?.remove())),a.after(i),e.info(`CSS file ${n} has been updated`)}else e.warn(`Server requested update for ${n}, but corresponding link not found in DOM. Update skipped.`)}scriptUpdateQueue=[];scriptUpdatePending=!1;async updateScript(t){let n=this.hotModuleMap.get(t.path);if(void 0===n)return;if(this.scriptUpdateQueue.push((async()=>{let a=new Map,s=t.path===t.acceptedPath,i=new Set;if(s)i.add(t.path);else for(let e of n.callbacks)e.deps.forEach((e=>{t.acceptedPath===e&&i.add(e)}));let o=n.callbacks.filter((e=>e.deps.some((e=>i.has(e)))));return await Promise.all(Array.from(i).map((async n=>{let s=this.depExecMap.get(n);s&&await s(this.urlDataMap.get(n));let[i,o]=n.split("?");try{let e=await import(`${c}${i.slice(1)}?import&t=${t.timestamp}${o?`&${o}`:""}`);a.set(n,e)}catch(t){e.error(`Request to ${i} failed. This could be due to syntax errors or importing non-existent modules. (See console for details). Attempting to reload to fix HMR failure in 2 seconds.`,t),setTimeout((()=>{location.reload()}),2e3)}}))),()=>{for(let e of o)e.fn(e.deps.map((e=>a.get(e))));let n=s?t.path:`${t.acceptedPath} updated via ${t.path}`;e.info(`Hot update completed: ${n}`)}})()),!1===this.scriptUpdatePending){this.scriptUpdatePending=!0,await Promise.resolve(),this.scriptUpdatePending=!1;let e=[...this.scriptUpdateQueue];this.scriptUpdateQueue=[],(await Promise.all(e)).forEach((e=>e?.()))}}clearnUrl(e){let t=new URL(e,location.toString());return t.searchParams.delete("direct"),t.pathname+t.search}},m=new Map,g=new Map,w=new Map;function M(e,t){let n=m.get(e);n?n.innerHTML=t:(n=document.createElement("style"),n.setAttribute("type","text/css"),n.innerHTML=t,document.head.appendChild(n)),m.set(e,n)}function y(e){let t=m.get(e);t&&(document.head.removeChild(t),m.delete(e))}class b{path;listeners=new Map;constructor(e){this.path=e,!1===f.urlDataMap.has(e)&&f.urlDataMap.set(e,{});let t=f.hotModuleMap.get(e);t&&(t.callbacks=[]);let n=w.get(e);if(n)for(let[e,t]of n){let n=g.get(e);n&&g.set(e,n.filter((e=>!1===t.includes(e))))}w.set(e,this.listeners)}get data(){return f.urlDataMap.get(this.path)}accept(e,t){"function"==typeof e?this.acceptDeps([this.path],e):(e=[e].flat()).length&&this.acceptDeps(e,t)}dispose(e){f.depExecMap.set(this.path,e)}prune(e){f.pruneMap.set(this.path,e)}on(e,t){this.addToListionMap(e,g,t),this.addToListionMap(e,this.listeners,t)}send(e,t){f.messageQueue.add(JSON.stringify({type:"custom",event:e,data:t})),f.sendMessages()}acceptDeps(e,t=()=>{}){let n=f.hotModuleMap.get(this.path)||{id:this.path,callbacks:[]};n.callbacks.push({deps:e,fn:t}),f.hotModuleMap.set(this.path,n)}addToListionMap(e,t,n){let a=t.get(e)||[];a.push(n),g.set(e,a)}}function x(e,t){if(!1===e.startsWith(".")||!1===e.startsWith("/"))return e;let n=e.replace(/#.*$/,"").replace(/\?.*$/,""),{search:a,hash:s}=new URL(e,"http://jokers.pub");return`${n}?${t}${a?`&${a.slice(1)}`:""}${s||""}`}export{b as JokerHotContext,i as clearErrorOverlay,o as createErrorOverlay,x as injectQuery,y as removeStyle,M as updateStyle};