@dadigua/web-terminal 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/API.md +4 -0
- package/README.md +3 -1
- package/dist/assets/index-BSlg9g_Q.js +29 -0
- package/dist/assets/index-ChYLGV1H.css +1 -0
- package/dist/index.html +2 -2
- package/dist-server/{app-3OE4ER7S.js → app-GCOLVKOP.js} +104 -6
- package/dist-server/{chunk-TD3NJESY.js → chunk-CAML55DK.js} +1 -1
- package/dist-server/cli.js +26 -4
- package/dist-server/{vscodeInstaller-WIM5VHDI.js → vscodeInstaller-CNVZA65C.js} +1 -1
- package/package.json +1 -1
- package/release/web-terminal.vsix +0 -0
- package/dist/assets/index-Bv4iPZiS.js +0 -27
- package/dist/assets/index-DAKKO3a9.css +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.xterm{cursor:text;position:relative;user-select:none;-ms-user-select:none;-webkit-user-select:none}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{position:absolute;top:0;z-index:5}.xterm .xterm-helper-textarea{padding:0;border:0;margin:0;position:absolute;opacity:0;left:-9999em;top:0;width:0;height:0;z-index:-5;white-space:nowrap;overflow:hidden;resize:none}.xterm .composition-view{background:#000;color:#fff;display:none;position:absolute;white-space:nowrap;z-index:1}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{background-color:#000;overflow-y:scroll;cursor:default;position:absolute;inset:0}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;left:0;top:0}.xterm-char-measure-element{display:inline-block;visibility:hidden;position:absolute;top:0;left:-9999em;line-height:normal}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{position:absolute;inset:0;z-index:10;color:transparent;pointer-events:none}.xterm .xterm-accessibility-tree:not(.debug) *::selection{color:transparent}.xterm .xterm-accessibility-tree{font-family:monospace;-webkit-user-select:text;user-select:text;white-space:pre}.xterm .xterm-accessibility-tree>div{transform-origin:left;width:fit-content}.xterm .live-region{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}.xterm-dim{opacity:1!important}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{text-decoration:double underline}.xterm-underline-3{text-decoration:wavy underline}.xterm-underline-4{text-decoration:dotted underline}.xterm-underline-5{text-decoration:dashed underline}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:overline underline}.xterm-overline.xterm-underline-2{text-decoration:overline double underline}.xterm-overline.xterm-underline-3{text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;position:absolute;top:0;right:0;pointer-events:none}.xterm-decoration-top{z-index:2;position:relative}.xterm .xterm-scrollable-element>.scrollbar{cursor:default}.xterm .xterm-scrollable-element>.scrollbar>.scra{cursor:pointer;font-size:11px!important}.xterm .xterm-scrollable-element>.visible{opacity:1;background:#0000;transition:opacity .1s linear;z-index:11}.xterm .xterm-scrollable-element>.invisible{opacity:0;pointer-events:none}.xterm .xterm-scrollable-element>.invisible.fade{transition:opacity .8s linear}.xterm .xterm-scrollable-element>.shadow{position:absolute;display:none}.xterm .xterm-scrollable-element>.shadow.top{display:block;top:0;left:3px;height:3px;width:100%;box-shadow:var(--vscode-scrollbar-shadow, #000) 0 6px 6px -6px inset}.xterm .xterm-scrollable-element>.shadow.left{display:block;top:3px;left:0;height:100%;width:3px;box-shadow:var(--vscode-scrollbar-shadow, #000) 6px 0 6px -6px inset}.xterm .xterm-scrollable-element>.shadow.top-left-corner{display:block;top:0;left:0;height:3px;width:3px}.xterm .xterm-scrollable-element>.shadow.top.left{box-shadow:var(--vscode-scrollbar-shadow, #000) 6px 0 6px -6px inset}:root{font-family:Inter,ui-sans-serif,system-ui,-apple-system,Segoe UI,sans-serif;color:#d9e5e9;background:#0b1219;font-synthesis:none}*{box-sizing:border-box}body{margin:0}button,input,.draft-input{font:inherit}button{cursor:pointer;border:1px solid #2a3c47;background:#182630;color:#d9e5e9;border-radius:8px;padding:8px 11px;transition:background .15s,border-color .15s}button:hover:not(:disabled){background:#25404a;border-color:#4c7580}button:disabled{opacity:.45;cursor:default}input,.draft-input{min-width:0;border:1px solid #2b414d;background:#111f29;color:#e9f1f3;border-radius:8px;padding:10px 11px;outline:none}input:focus,.draft-input:focus{border-color:#55b5aa;box-shadow:0 0 0 3px #55b5aa22}.primary{background:#4fb6a8;color:#06201f;border-color:#4fb6a8;font-weight:700}.primary:hover:not(:disabled){background:#70d0c2;color:#06201f}.app{display:flex;flex-direction:column;height:var(--app-height,100dvh);min-height:0;position:fixed;top:var(--app-top,0px);left:0;right:0}.brand-mark{display:inline-grid;place-items:center;width:36px;height:36px;border-radius:9px;background:#174a4a;color:#7de8d4;font-weight:800;font-size:19px;font-family:monospace}.tabs-bar{position:relative;display:flex;flex:none;align-items:center;min-width:0;min-height:32px;background:#0d1821;border-bottom:1px solid #263640;padding:3px 5px;gap:3px;font-family:ui-sans-serif,system-ui,-apple-system,Segoe UI,sans-serif;font-size:12px;container-type:inline-size}.session-list{display:flex;align-items:stretch;gap:2px;overflow-x:auto;overflow-y:hidden;min-width:0;flex:1;scrollbar-width:none}.session-list::-webkit-scrollbar{display:none}.session{display:flex;align-items:center;flex:0 0 var(--tab-width,240px);width:var(--tab-width,240px);min-width:64px;max-width:240px;height:26px;container:session-tab / inline-size;border-radius:4px;background:#13212b}.session.active{background:#263a45;box-shadow:inset 0 -1px #80cdbf}.session-select{display:flex;align-items:center;gap:4px;flex:1;min-width:0;height:26px;text-align:left;background:transparent;border:0;border-radius:4px;padding:3px 4px;overflow:hidden}.session-select strong{flex:1;min-width:0;font-size:12px;font-weight:400;line-height:16px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.session-select small{flex:0 1 auto;font-size:11px;color:#849da7;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:44px}.session .end,.tab-more{display:grid;place-items:center;flex:none;width:16px;height:22px;border:0;background:transparent;font-size:15px;line-height:1;color:#9ab0bc;padding:0;border-radius:3px;opacity:0}.tab-more{display:none}.session:hover .tab-more,.session:focus-within .tab-more{display:grid;opacity:1}.session:hover .end,.session:focus-within .end,.session.active .end{opacity:1}.dot{display:inline-block;width:8px;height:8px;border-radius:50%;background:#6e8290;flex:none}.dot.live{background:#64d6ae;box-shadow:0 0 0 2px #64d6ae20}.dot.offline{background:transparent;border:1px solid #dc8c7f}.command-icon{flex:none;font-family:monospace;font-size:12px;color:#b5d8d2}.command-icon.claude{color:#db997c}.tab-actions{display:flex;flex:none;gap:1px}.tab-actions button{display:grid;place-items:center;min-width:26px;height:26px;border:0;background:transparent;padding:3px;font-size:18px;border-radius:4px}.tab-actions svg{width:15px;height:15px}.workspace{flex:1;min-width:0;min-height:0;display:flex;flex-direction:column}.session-group{display:flex;align-items:center;gap:2px;flex:none;min-width:min-content;box-shadow:inset 0 -2px var(--group-color);padding:0 1px}.session-group.collapsed{flex:none;box-shadow:none}.session-group-header{display:flex;align-items:center;flex:none;max-width:136px;gap:1px}.session-group-label{display:flex;align-items:center;gap:4px;height:24px;min-width:0;max-width:122px;padding:2px 5px;border:1px solid transparent;border-radius:4px;background:var(--group-color);color:#101821;font-size:12px;font-weight:500;white-space:nowrap}.session-group-label:hover:not(:disabled){background:var(--group-color);border-color:#e4eef8}.session-group-label.active{border-color:#edf7ff;box-shadow:0 0 0 1px #edf7ff33}.group-name{overflow:hidden;text-overflow:ellipsis;min-width:0}.group-count{font-size:10px;opacity:.8}.group-chevron{font-size:13px;flex:none;line-height:14px}.group-output{width:8px;height:8px;flex:none;border-radius:50%;border:1.5px solid #10182138;border-top-color:#101821;border-right-color:#101821;animation:output-spin .7s linear infinite}.group-more{flex:none;width:14px;height:22px;padding:0;border:0;border-radius:3px;background:transparent;font-size:15px;color:var(--group-color);opacity:0}.session-group-header:hover .group-more,.session-group-header:focus-within .group-more{opacity:1}.tabs-bar button:focus-visible,.tab-menu button:focus-visible{outline:1px solid #9ed8ee;outline-offset:-1px}.tab-menu{position:fixed;z-index:120;width:218px;max-width:calc(100vw - 16px);max-height:calc(100dvh - 16px);overflow-y:auto;padding:4px;border:1px solid #39515f;border-radius:6px;background:#172630;box-shadow:0 6px 24px #0007;font:12px/18px ui-sans-serif,system-ui,-apple-system,Segoe UI,sans-serif;color:#d9e5e9}.tab-menu button{display:flex;align-items:center;gap:7px;width:100%;min-height:28px;text-align:left;padding:4px 7px;border:0;border-radius:3px;background:transparent;font-size:12px;overflow-wrap:anywhere}.tab-menu button:hover:not(:disabled){background:#29414e}.tab-menu-caption{padding:6px 7px 2px;color:#91a8b5;font-size:11px}.tab-menu hr{border:0;border-top:1px solid #30444f;margin:4px}.menu-color{flex:none;width:8px;height:8px;border-radius:50%}.menu-check{margin-left:auto}.session-group-dialog{width:min(92vw,320px);padding:18px}.session-group-dialog h2{font-size:15px}.session-group-dialog label{display:block;font-size:12px;margin:12px 0 5px}.session-group-dialog input{width:100%;font-size:12px;padding:7px 9px}.group-colors{display:flex;gap:5px;flex-wrap:wrap;border:0;padding:0;margin:14px 0}.group-colors legend{font-size:12px;margin-bottom:8px}.group-colors button{display:grid;place-items:center;width:23px;height:23px;min-width:23px;padding:0;border:2px solid transparent;border-radius:50%;color:#101821;font-size:12px}.group-colors button[aria-pressed=true]{border-color:#e8f3ff}.session-group-dialog .session-close-actions button{font-size:12px;padding:6px 10px}@container session-tab (max-width:115px){.session-select small{display:none}}@media(hover:none)and (pointer:coarse){.tabs-bar{min-height:38px}.session,.session-select{height:32px}.session{min-width:94px}.session .end,.tab-more,.group-more{display:grid;width:22px;height:30px;opacity:1}.session-group-label{height:30px}.tab-actions button{height:32px;min-width:30px}}.content{flex:1;min-height:0;display:flex}.terminal-pane{flex:1;min-width:0;display:flex;flex-direction:column;background:#101821}.terminal-wrap{flex:1;min-height:0;padding:15px 12px 4px;overflow:auto;overscroll-behavior:contain}.terminal-host{width:100%;height:100%;min-height:0}.xterm{height:100%}.draft-row{display:flex;min-width:0}.draft-row .draft-input{flex:1;font-size:12px}.mobile-keys{display:none}.upload-state{display:flex;align-items:center;gap:10px;justify-content:space-between;background:#18313a;padding:9px 14px;color:#b5e8df;font-size:12px;word-break:break-all}.upload-state.error,.error{color:#ffb3aa}.upload-state button{margin-left:auto;font-size:11px;padding:4px 7px;white-space:nowrap}.hover-card{position:fixed;z-index:10;width:220px;padding:7px;background:#1a2c35;border:1px solid #45616b;border-radius:9px;box-shadow:0 12px 35px #0009;pointer-events:none}.hover-card img{display:block;width:100%;max-height:165px;object-fit:contain}.hover-card span{display:block;font-size:11px;margin-top:6px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.hidden{display:none}.auth-shell{min-height:100dvh;display:grid;place-items:center;padding:20px;background:radial-gradient(circle at 50% 28%,#163039,#0b1219 55%)}.auth-card{width:min(100%,390px);padding:32px;background:#12212b;border:1px solid #2b414b;border-radius:17px;box-shadow:0 20px 70px #0005;display:grid;gap:13px}.auth-card h1{font-size:23px;margin:8px 0 0}.auth-card p{font-size:13px;color:#96adb7;line-height:1.5;margin:0 0 14px}.auth-card label{font-size:12px;color:#a7bec6}.auth-card .primary{margin-top:6px}.auth-card .error{font-size:12px}@media(max-width:760px){.content{position:relative}.terminal-wrap{padding:8px 5px 0}}.empty-session{position:absolute;z-index:2;inset:0 0 75px;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;background:#101821;color:#d5e7e9}.empty-session strong{font-size:18px}.empty-session p{font-size:13px;color:#89a3ad}.empty-session button{margin-top:10px}.terminal-pane{position:relative}.workspace{min-height:0}.upload-thumbnail{width:38px;height:30px;object-fit:cover;border-radius:4px;flex:none}.upload-state>span{flex:1}.upload-state button{margin-left:0}@media(hover:none)and (pointer:coarse){.mobile-keys{display:flex;gap:4px;padding:6px;flex-wrap:wrap;border-top:1px solid #243640}.mobile-keys button{flex:1;min-width:34px;min-height:42px;font-size:12px;padding:6px 4px;touch-action:manipulation}}.session-close-dialog{width:min(92vw,380px);box-sizing:border-box;border:1px solid #38535f;border-radius:12px;padding:22px;background:#12212b;color:#d9e5e9;box-shadow:0 20px 70px #0008}.session-close-dialog::backdrop{background:#0008}.session-close-dialog h2{font-size:17px;margin:0 0 12px;overflow-wrap:anywhere}.session-close-dialog p{font-size:13px;line-height:1.6;color:#a7bec6}.session-close-dialog .error{color:#ffb3aa}.session-close-actions{display:flex;justify-content:flex-end;gap:10px;margin-top:20px}.session-ended-dialog{width:min(92vw,440px)}.session-ended-path{overflow-wrap:anywhere;font-family:ui-monospace,monospace}.session-ended-dialog .session-close-actions{flex-wrap:wrap}.terminal-progress{display:inline-flex;flex:none;width:14px;height:14px;color:#7bdfcd}.terminal-progress svg{transform:rotate(-90deg)}.progress-track{opacity:.2}.progress-state-2{color:#ed9388}.progress-state-4{color:#e3b967}.progress-state-3 svg{animation:output-spin .7s linear infinite}@media(prefers-reduced-motion:reduce){.progress-state-3 svg{animation:none}}.message-layer{position:fixed;z-index:100;top:max(16px,env(safe-area-inset-top));left:0;right:0;display:flex;justify-content:center;padding:0 16px;pointer-events:none}.message-toast{display:flex;align-items:center;gap:10px;max-width:min(520px,100%);padding:11px 14px;border:1px solid #3a515e;border-radius:9px;background:#20323e;color:#e7f0f3;box-shadow:0 6px 24px #0006;font-size:13px;line-height:1.5;pointer-events:auto;animation:message-appear .16s ease-out}.message-icon{flex:none;display:grid;place-items:center;width:18px;height:18px;border-radius:50%;background:#58c1b2;color:#09231f;font-weight:700;font-family:serif}.message-text{overflow-wrap:anywhere;min-width:0}.message-close{flex:none;padding:0 3px;border:0;background:transparent;color:#9fb5c0;font-size:19px;line-height:22px}@keyframes message-appear{0%{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:translateY(0)}}@media(prefers-reduced-motion:reduce){.message-toast{animation:none}}.directory-picker{width:min(560px,calc(100vw - 24px));max-height:calc(100dvh - 24px);border:1px solid #38535f;border-radius:12px;padding:18px;background:#12212b;color:#d9e5e9;box-shadow:0 20px 70px #0008;overflow:auto}.directory-picker::backdrop{background:#0007}.directory-picker header,.directory-picker footer{display:flex;align-items:center;justify-content:space-between;gap:8px}.directory-picker header button{background:transparent;border:0;font-size:20px}.directory-picker footer{justify-content:flex-end;margin-top:14px}.directory-path{display:flex;gap:6px;margin:14px 0 8px}.directory-path input{flex:1;width:0;font-size:12px}.directory-path button{padding:7px 9px;flex:none}.directory-filter{width:100%;font-size:12px}.directory-entries{height:min(260px,35dvh);overflow:auto;margin-top:8px}.directory-entries button{display:flex;align-items:center;gap:10px;width:100%;text-align:left;border:0;background:transparent;border-radius:5px;font-size:13px;overflow-wrap:anywhere}.directory-entries button span:last-child{margin-left:auto}.directory-entries p{font-size:12px;color:#8fa7af;padding:12px}.workspace-shortcuts small{display:block;color:#8fa7af;margin-bottom:6px}.workspace-shortcuts>div{display:flex;flex-wrap:wrap;gap:6px;max-height:100px;overflow:auto}.workspace-shortcuts button{font-size:12px;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.directory-picker .error{font-size:12px;overflow-wrap:anywhere}@media(hover:none)and (pointer:coarse){.draft-row .draft-input{font-size:16px}.mobile-keys{flex-wrap:nowrap;overflow-x:auto;flex:none}.mobile-keys button{min-width:38px}.app .terminal-pane{min-height:0}}.draft-input{min-height:40px;max-height:100px;line-height:20px;white-space:pre-wrap;overflow-wrap:anywhere;overflow-y:auto;cursor:text}.draft-input:empty:before{content:attr(data-placeholder);color:#78909c;pointer-events:none}.session-pane[hidden]{display:none}.composer-dock{position:relative;flex:none;height:calc(112px + env(safe-area-inset-bottom,0px));container-type:inline-size;z-index:6}.composer-panel{position:absolute;left:12px;right:12px;bottom:max(10px,env(safe-area-inset-bottom));display:flex;flex-direction:column;gap:8px;padding:8px;border:1px solid #304953;border-radius:13px;background:#12232c;box-shadow:0 -6px 22px #0003}.composer-panel:focus-within{border-color:#4b978f;box-shadow:0 -6px 22px #0003,0 0 0 2px #4fb6a812}.composer-panel .draft-input{width:100%;min-height:38px;max-height:min(236px,max(38px,calc(var(--app-height,100dvh) - 180px)));padding:8px;border:0;border-radius:6px;background:transparent;font-size:14px;line-height:22px;box-shadow:none;scrollbar-width:thin;overscroll-behavior:contain}.composer-actions,.composer-tools{display:flex;align-items:center;gap:4px}.composer-actions{gap:8px;min-height:32px}.composer-tools{flex:none}.composer-tools button{display:inline-flex;align-items:center;justify-content:center;height:30px;padding:4px 7px;border:0;border-radius:6px;background:transparent;color:#96b0b9;font-size:11px}.composer-tools button:hover:not(:disabled){background:#223e48;color:#def3ee}.composer-divider{height:14px;width:1px;background:#30444d;margin:0 3px}.composer-hint{flex:1;text-align:right;color:#78939e;font-size:10px;white-space:nowrap}.composer-send{display:inline-flex;align-items:center;justify-content:center;gap:7px;margin-left:auto;min-width:70px;height:32px;padding:6px 11px;border:1px solid #4fb6a8;border-radius:8px;background:#4fb6a8;color:#062c28;font-size:12px;font-weight:600}.composer-send:hover:not(:disabled){border-color:#76d5c5;background:#76d5c5}.composer-send:disabled{opacity:1;border-color:#2c434c;background:#1a3039;color:#6c8791}.composer-attachments{display:flex;align-items:center;gap:8px;padding:6px;border:1px solid #304953;border-radius:11px;background:#142a31;min-width:0}.attachment-count{display:inline-flex;align-items:center;gap:3px;flex:none;font-size:12px;color:#b5d8d2;white-space:nowrap}.attachment-list{display:flex;gap:6px;min-width:0;flex:1;overflow-x:auto;scrollbar-width:thin}.attachment-card{flex:none;width:112px;padding:4px;border:1px solid #39545e;border-radius:8px;background:#10212a;overflow:hidden}.attachment-card .upload-thumbnail,.attachment-text{display:block;width:100%;height:76px;margin:0;border:1px solid #2b414d;border-radius:5px;background:#0b1821;object-fit:cover}.attachment-text{padding:5px;font:9px/12px ui-monospace,monospace;white-space:pre-wrap;overflow:hidden;overflow-wrap:anywhere;color:#b5d8d2}.attachment-caption{display:flex;align-items:center;gap:3px;height:23px;font-size:11px}.attachment-caption span{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.attachment-caption button{border:0;background:transparent;padding:0 3px;font-size:17px;color:#96b0b9}.attachment-status{display:flex;align-items:center;justify-content:space-between;font-size:9px;line-height:15px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:#86a59f}.attachment-status button{border:0;background:transparent;font-size:10px;padding:0 2px}.attachment-card.error{border-color:#bf766b}.attachment-card.error .attachment-status{color:#ffb3aa}.attachment-clear{flex:none;border:0;background:#263e42;font-size:11px;padding:5px 7px;white-space:nowrap}.composer-attachments{max-height:160px}@container (max-width:360px){.composer-attachments{gap:4px}.attachment-count{font-size:10px}.attachment-clear{font-size:10px;padding:5px 4px}}.composer-panel .mobile-keys{padding:0;border:0}@container (max-width:480px){.composer-hint{display:none}}@media(hover:none)and (pointer:coarse){.composer-dock{height:calc(124px + env(safe-area-inset-bottom,0px))}.composer-panel{left:4px;right:4px;bottom:max(6px,env(safe-area-inset-bottom));gap:2px;padding:4px;border-radius:10px}.composer-panel .draft-input{min-height:32px;padding:4px 6px;font-size:16px;line-height:24px}.composer-actions{gap:4px}.composer-tools{gap:2px}.composer-tools button{height:36px;min-width:36px}.composer-divider{margin:0 1px}.composer-send{height:36px;min-width:64px;padding:6px 8px}.composer-panel .mobile-keys{gap:2px}.composer-panel .mobile-keys button{min-height:36px;border-color:transparent;background:transparent;border-radius:6px}.composer-panel .mobile-keys button:hover:not(:disabled){background:#223e48}}.client-settings label{display:block;margin:14px 0 8px;font-size:13px}.client-settings input{width:100%}.font-preview{padding:12px;border:1px solid #304953;border-radius:8px;overflow-wrap:anywhere}.terminal-selection-handle{position:absolute;z-index:15;width:40px;height:44px;padding:0;border:0;background:transparent;border-radius:0;touch-action:none;cursor:grab}.terminal-selection-handle:before{content:"";position:absolute;left:19px;top:0;width:2px;height:22px;background:#7bdfcd}.terminal-selection-handle:after{content:"";position:absolute;left:12px;top:18px;width:16px;height:16px;border-radius:50%;background:#7bdfcd;border:2px solid #101821}.terminal-selection-handle:hover:not(:disabled){background:transparent}.terminal-touch-actions{position:absolute;z-index:16;display:flex;gap:4px;padding:4px;border:1px solid #42616c;border-radius:9px;background:#182b35;box-shadow:0 4px 18px #0006;touch-action:none}.terminal-touch-actions button{min-width:48px;min-height:40px;padding:6px 10px;font-size:13px}.terminal-touch-actions[hidden],.terminal-selection-handle[hidden]{display:none}.client-settings{width:min(92vw,520px);max-height:calc(var(--app-height,100dvh) - 32px);overflow:auto}.settings-section{border-top:1px solid #304953;margin-top:18px;padding-top:16px}.settings-section h3{font-size:14px;margin:0 0 10px}.client-settings select{width:100%;padding:10px 11px;border:1px solid #38535f;border-radius:8px;background:#111f29;color:#e9f1f3;font:inherit}.client-settings .settings-section p{margin:8px 0 12px}.tab-actions button[aria-label=设置]{display:inline-flex;align-items:center;justify-content:center}.composer-tools .copy-mode-toggle[aria-pressed=true]{background:#28594f;color:#a6f3df;box-shadow:inset 0 0 0 1px #5abfa9}.dot.live.output-active{background:transparent;border:1.5px solid #64d6ae35;border-top-color:#8df8d4;border-right-color:#8df8d4;box-shadow:0 0 5px #64d6ae40;animation:output-spin .7s linear infinite}@keyframes output-spin{to{transform:rotate(360deg)}}@media(prefers-reduced-motion:reduce){.dot.live.output-active,.group-output{animation:none}.dot.live.output-active{border-color:#8df8d4}.group-output{border-color:#101821}}.file-preview-dialog{width:min(960px,calc(100vw - 32px));max-height:calc(var(--app-height,100dvh) - 32px);padding:18px;border:1px solid #38535f;border-radius:13px;background:#12212b;color:#d9e5e9;box-shadow:0 20px 70px #0008;overflow:auto}.file-preview-dialog::backdrop{background:#0009}.file-preview-dialog header,.file-preview-dialog footer{display:flex;align-items:center;gap:10px}.file-preview-dialog header h2{min-width:0;flex:1;font-size:17px;overflow-wrap:anywhere;margin:0}.file-preview-dialog header button{border:0;background:transparent;font-size:22px;padding:2px 8px}.file-preview-dialog .file-path{font-size:11px;color:#8ea7b0;overflow-wrap:anywhere;line-height:1.5}.file-preview-content{max-height:calc(var(--app-height,100dvh) - 210px);min-height:80px;overflow:auto;border:1px solid #2b414d;border-radius:8px;background:#0b1821}.file-preview-content pre{margin:0;padding:14px;font:12px/1.6 ui-monospace,monospace;white-space:pre;tab-size:2}.file-preview-content img{display:block;max-width:100%;max-height:calc(var(--app-height,100dvh) - 230px);object-fit:contain;margin:auto}.file-preview-content>p{margin:16px;font-size:13px;overflow-wrap:anywhere}.file-preview-dialog footer{justify-content:flex-end;margin-top:14px;font-size:12px}.file-preview-dialog footer span{margin-right:auto;color:#8ea7b0}.file-preview-dialog footer button{font-size:12px}.session[draggable=true],.session-group-header[draggable=true]{cursor:grab}.session.dragging,.session-group.dragging{opacity:.45}.session.drop-before{box-shadow:inset 2px 0 #a3e4d5}.session.drop-after{box-shadow:inset -2px 0 #a3e4d5}.session-group-header.drop-group{outline:2px solid var(--group-color);outline-offset:1px;border-radius:4px}.session-list.drop-end:after{content:"";flex:none;width:2px;background:#a3e4d5}
|
package/dist/index.html
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
<!doctype html>
|
|
2
|
-
<html lang="zh-CN"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width, initial-scale=1.0"/><meta name="theme-color" content="#101419"/><link rel="icon" href="/favicon.svg"/><title>Web Terminal</title> <script type="module" crossorigin src="/assets/index-
|
|
3
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
2
|
+
<html lang="zh-CN"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width, initial-scale=1.0"/><meta name="theme-color" content="#101419"/><link rel="icon" href="/favicon.svg"/><title>Web Terminal</title> <script type="module" crossorigin src="/assets/index-BSlg9g_Q.js"></script>
|
|
3
|
+
<link rel="stylesheet" crossorigin href="/assets/index-ChYLGV1H.css">
|
|
4
4
|
</head><body><div id="root"></div></body></html>
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
serviceName,
|
|
3
3
|
serviceProtocol,
|
|
4
4
|
serviceVersion
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-CAML55DK.js";
|
|
6
6
|
|
|
7
7
|
// src/server/app.ts
|
|
8
8
|
import express from "express";
|
|
@@ -289,10 +289,29 @@ var TerminalScreen = class {
|
|
|
289
289
|
cursorVisible = true;
|
|
290
290
|
mouseEncoding = 0;
|
|
291
291
|
margins = [1, 30];
|
|
292
|
-
|
|
292
|
+
progress;
|
|
293
|
+
constructor(onTitle, onResponse, onProgress = () => {
|
|
294
|
+
}) {
|
|
293
295
|
this.terminal.loadAddon(this.serializer);
|
|
294
296
|
this.terminal.onTitleChange((title) => onTitle(title.replace(/[\x00-\x1f\x7f]/g, "").slice(0, 512)));
|
|
295
297
|
this.terminal.onData(onResponse);
|
|
298
|
+
const setProgress = (progress) => {
|
|
299
|
+
this.progress = progress;
|
|
300
|
+
onProgress(progress);
|
|
301
|
+
};
|
|
302
|
+
this.terminal.parser.registerOscHandler(9, (data) => {
|
|
303
|
+
if (!data.startsWith("4;")) return false;
|
|
304
|
+
const match = /^4;([0-4])(?:;(\d+))?$/.exec(data);
|
|
305
|
+
if (!match) return true;
|
|
306
|
+
const state = Number(match[1]);
|
|
307
|
+
if (state === 0) setProgress(void 0);
|
|
308
|
+
else {
|
|
309
|
+
const previous = this.progress?.value ?? 0;
|
|
310
|
+
const value = state === 3 ? previous : match[2] !== void 0 ? Math.min(100, Number(match[2])) : state === 1 ? 0 : previous;
|
|
311
|
+
setProgress({ state, value });
|
|
312
|
+
}
|
|
313
|
+
return true;
|
|
314
|
+
});
|
|
296
315
|
for (const [code, color] of [[10, "d8d8/e3e3/e8e8"], [11, "1010/1818/2121"]]) {
|
|
297
316
|
this.terminal.parser.registerOscHandler(code, (data) => {
|
|
298
317
|
if (data !== "?") return false;
|
|
@@ -314,6 +333,7 @@ var TerminalScreen = class {
|
|
|
314
333
|
this.cursorVisible = true;
|
|
315
334
|
this.mouseEncoding = 0;
|
|
316
335
|
this.margins = [1, this.terminal.rows];
|
|
336
|
+
setProgress(void 0);
|
|
317
337
|
return false;
|
|
318
338
|
});
|
|
319
339
|
}
|
|
@@ -377,7 +397,7 @@ var Sessions = class {
|
|
|
377
397
|
for (const record of records) {
|
|
378
398
|
if (!/^[a-f0-9-]{36}$/.test(record.id)) continue;
|
|
379
399
|
const { id, name, cwd, createdAt } = record;
|
|
380
|
-
const info = { id, name, cwd, createdAt, running: false };
|
|
400
|
+
const info = { id, name, cwd, createdAt, running: false, outputActive: false };
|
|
381
401
|
this.entries.set(info.id, this.makeSession(info));
|
|
382
402
|
}
|
|
383
403
|
}
|
|
@@ -386,12 +406,23 @@ var Sessions = class {
|
|
|
386
406
|
files;
|
|
387
407
|
entries = /* @__PURE__ */ new Map();
|
|
388
408
|
shuttingDown = false;
|
|
409
|
+
watchers = /* @__PURE__ */ new Set();
|
|
410
|
+
refreshTimer;
|
|
411
|
+
refreshing = false;
|
|
389
412
|
makeSession(info) {
|
|
390
413
|
const session = { info, clients: /* @__PURE__ */ new Map(), pendingBytes: 0, screen: new TerminalScreen(
|
|
391
414
|
(title) => {
|
|
392
|
-
info.title
|
|
415
|
+
if (info.title !== title) {
|
|
416
|
+
info.title = title;
|
|
417
|
+
this.publish();
|
|
418
|
+
}
|
|
393
419
|
},
|
|
394
|
-
(data) => session.process?.write(data)
|
|
420
|
+
(data) => session.process?.write(data),
|
|
421
|
+
(progress) => {
|
|
422
|
+
if (info.progress?.state === progress?.state && info.progress?.value === progress?.value) return;
|
|
423
|
+
info.progress = progress;
|
|
424
|
+
this.publish();
|
|
425
|
+
}
|
|
395
426
|
) };
|
|
396
427
|
return session;
|
|
397
428
|
}
|
|
@@ -420,13 +451,59 @@ var Sessions = class {
|
|
|
420
451
|
async list() {
|
|
421
452
|
return Promise.all([...this.entries.keys()].map((id) => this.current(id)));
|
|
422
453
|
}
|
|
454
|
+
publish(ws) {
|
|
455
|
+
const message = { type: "sessions", sessions: [...this.entries.values()].map((session) => ({ ...session.info })) };
|
|
456
|
+
if (ws) send(ws, message);
|
|
457
|
+
else for (const watcher of this.watchers) send(watcher, message);
|
|
458
|
+
}
|
|
459
|
+
watch(ws) {
|
|
460
|
+
this.watchers.add(ws);
|
|
461
|
+
this.publish(ws);
|
|
462
|
+
ws.once("close", () => {
|
|
463
|
+
this.watchers.delete(ws);
|
|
464
|
+
if (!this.watchers.size) {
|
|
465
|
+
clearInterval(this.refreshTimer);
|
|
466
|
+
this.refreshTimer = void 0;
|
|
467
|
+
}
|
|
468
|
+
});
|
|
469
|
+
if (!this.refreshTimer) this.refreshTimer = setInterval(() => void this.refresh(), 5e3);
|
|
470
|
+
void this.refresh();
|
|
471
|
+
}
|
|
472
|
+
async refresh() {
|
|
473
|
+
if (this.refreshing || this.shuttingDown) return;
|
|
474
|
+
this.refreshing = true;
|
|
475
|
+
try {
|
|
476
|
+
await this.list();
|
|
477
|
+
if (!this.shuttingDown) this.publish();
|
|
478
|
+
} catch (error) {
|
|
479
|
+
console.error("\u4F1A\u8BDD\u72B6\u6001\u66F4\u65B0\u5931\u8D25", error);
|
|
480
|
+
} finally {
|
|
481
|
+
this.refreshing = false;
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
stopActivity(session) {
|
|
485
|
+
clearTimeout(session.activityTimer);
|
|
486
|
+
session.activityTimer = void 0;
|
|
487
|
+
session.info.outputActive = false;
|
|
488
|
+
}
|
|
489
|
+
outputActivity(session) {
|
|
490
|
+
clearTimeout(session.activityTimer);
|
|
491
|
+
if (!session.info.outputActive) {
|
|
492
|
+
session.info.outputActive = true;
|
|
493
|
+
this.publish();
|
|
494
|
+
}
|
|
495
|
+
session.activityTimer = setTimeout(() => {
|
|
496
|
+
this.stopActivity(session);
|
|
497
|
+
this.publish();
|
|
498
|
+
}, 800);
|
|
499
|
+
}
|
|
423
500
|
async create(name, cwd) {
|
|
424
501
|
if (this.entries.size >= 32) throw new HttpError(409, "\u6700\u591A\u4FDD\u7559 32 \u4E2A\u4F1A\u8BDD\uFF0C\u8BF7\u7ED3\u675F\u4E0D\u9700\u8981\u7684\u4F1A\u8BDD");
|
|
425
502
|
if (name !== void 0 && (typeof name !== "string" || name.length > 80)) throw new HttpError(400, "\u4F1A\u8BDD\u540D\u79F0\u6700\u591A 80 \u5B57\u7B26");
|
|
426
503
|
if (cwd !== void 0 && typeof cwd !== "string") throw new HttpError(400, "\u5DE5\u4F5C\u76EE\u5F55\u65E0\u6548");
|
|
427
504
|
const dir = await this.files.directory(cwd || this.config.defaultCwd);
|
|
428
505
|
const id = randomUUID();
|
|
429
|
-
const info = { id, name: name?.trim() || `\u7EC8\u7AEF ${this.entries.size + 1}`, cwd: dir, createdAt: (/* @__PURE__ */ new Date()).toISOString(), running: true };
|
|
506
|
+
const info = { id, name: name?.trim() || `\u7EC8\u7AEF ${this.entries.size + 1}`, cwd: dir, createdAt: (/* @__PURE__ */ new Date()).toISOString(), running: true, outputActive: false };
|
|
430
507
|
const session = this.makeSession(info);
|
|
431
508
|
try {
|
|
432
509
|
this.entries.set(id, session);
|
|
@@ -437,6 +514,7 @@ var Sessions = class {
|
|
|
437
514
|
throw error;
|
|
438
515
|
}
|
|
439
516
|
this.save();
|
|
517
|
+
this.publish();
|
|
440
518
|
return info;
|
|
441
519
|
}
|
|
442
520
|
spawnTerminal(command, args, cwd, cols, rows) {
|
|
@@ -456,6 +534,8 @@ var Sessions = class {
|
|
|
456
534
|
const terminalProcess = this.spawnTerminal(this.config.shell, shellArgs, session.info.cwd, 100, 30);
|
|
457
535
|
session.process = terminalProcess;
|
|
458
536
|
terminalProcess.onData((data) => {
|
|
537
|
+
if (this.shuttingDown || this.entries.get(session.info.id) !== session) return;
|
|
538
|
+
if (data) this.outputActivity(session);
|
|
459
539
|
session.pendingBytes += data.length;
|
|
460
540
|
if (session.pendingBytes > 256 * 1024) terminalProcess.pause();
|
|
461
541
|
void session.screen.write(data, () => {
|
|
@@ -469,7 +549,10 @@ var Sessions = class {
|
|
|
469
549
|
if (this.shuttingDown) return;
|
|
470
550
|
void session.screen.run(() => {
|
|
471
551
|
session.info.running = false;
|
|
552
|
+
session.info.progress = void 0;
|
|
553
|
+
this.stopActivity(session);
|
|
472
554
|
this.save();
|
|
555
|
+
this.publish();
|
|
473
556
|
for (const ws of session.clients.keys()) {
|
|
474
557
|
send(ws, { type: "exit", exitCode });
|
|
475
558
|
ws.close(4404, "\u4F1A\u8BDD\u5DF2\u7ED3\u675F");
|
|
@@ -549,17 +632,24 @@ var Sessions = class {
|
|
|
549
632
|
}
|
|
550
633
|
async remove(id) {
|
|
551
634
|
const session = this.get(id);
|
|
635
|
+
this.stopActivity(session);
|
|
552
636
|
session.process?.kill();
|
|
553
637
|
for (const ws of session.clients.keys()) ws.close(1e3, "\u4F1A\u8BDD\u5DF2\u7ED3\u675F");
|
|
554
638
|
this.entries.delete(id);
|
|
555
639
|
this.save();
|
|
640
|
+
this.publish();
|
|
556
641
|
await session.screen.dispose();
|
|
557
642
|
await this.files.removeUploads(id);
|
|
558
643
|
}
|
|
559
644
|
async shutdown() {
|
|
560
645
|
this.shuttingDown = true;
|
|
561
646
|
this.save();
|
|
647
|
+
clearInterval(this.refreshTimer);
|
|
648
|
+
this.refreshTimer = void 0;
|
|
649
|
+
for (const ws of this.watchers) ws.close(1012, "\u670D\u52A1\u91CD\u542F\u4E2D");
|
|
650
|
+
this.watchers.clear();
|
|
562
651
|
for (const session of this.entries.values()) {
|
|
652
|
+
this.stopActivity(session);
|
|
563
653
|
for (const ws of session.clients.keys()) ws.close(1012, "\u670D\u52A1\u91CD\u542F\u4E2D");
|
|
564
654
|
session.process?.kill();
|
|
565
655
|
}
|
|
@@ -695,6 +785,7 @@ async function createApp(config, options = {}) {
|
|
|
695
785
|
});
|
|
696
786
|
wss.on("connection", (ws) => {
|
|
697
787
|
let sessionId;
|
|
788
|
+
let watching = false;
|
|
698
789
|
const timer = setTimeout(() => ws.close(4401, "\u9700\u8981 token"), 5e3);
|
|
699
790
|
ws.once("close", () => clearTimeout(timer));
|
|
700
791
|
ws.on("error", () => {
|
|
@@ -703,6 +794,7 @@ async function createApp(config, options = {}) {
|
|
|
703
794
|
try {
|
|
704
795
|
if (binary) throw new Error("\u6D88\u606F\u683C\u5F0F\u65E0\u6548");
|
|
705
796
|
const message = JSON.parse(raw.toString());
|
|
797
|
+
if (watching) throw new Error("\u4F1A\u8BDD\u72B6\u6001\u8BA2\u9605\u53EA\u652F\u6301\u8BFB\u53D6");
|
|
706
798
|
if (!sessionId) {
|
|
707
799
|
if (message.type !== "auth" || !validToken(message.token, config.token)) {
|
|
708
800
|
ws.close(4401, "token \u65E0\u6548");
|
|
@@ -713,6 +805,12 @@ async function createApp(config, options = {}) {
|
|
|
713
805
|
ws.close(4406, "\u8BF7\u5237\u65B0\u9875\u9762");
|
|
714
806
|
return;
|
|
715
807
|
}
|
|
808
|
+
if (message.scope === "sessions") {
|
|
809
|
+
watching = true;
|
|
810
|
+
clearTimeout(timer);
|
|
811
|
+
sessions.watch(ws);
|
|
812
|
+
return;
|
|
813
|
+
}
|
|
716
814
|
if (typeof message.sessionId !== "string") throw new Error("\u4F1A\u8BDD\u65E0\u6548");
|
|
717
815
|
const session = sessions.get(message.sessionId);
|
|
718
816
|
sessionId = session.info.id;
|
package/dist-server/cli.js
CHANGED
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
serviceName,
|
|
3
3
|
serviceProtocol,
|
|
4
4
|
serviceVersion
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-CAML55DK.js";
|
|
6
6
|
|
|
7
7
|
// src/cli.ts
|
|
8
8
|
import { fileURLToPath } from "node:url";
|
|
@@ -72,7 +72,7 @@ import { randomUUID } from "node:crypto";
|
|
|
72
72
|
import { parse as parse2, stringify } from "yaml";
|
|
73
73
|
|
|
74
74
|
// src/service/probe.ts
|
|
75
|
-
import { connect } from "node:net";
|
|
75
|
+
import { connect, createServer } from "node:net";
|
|
76
76
|
function isLocalServer(input) {
|
|
77
77
|
const url = new URL(normalizeServerUrl(input));
|
|
78
78
|
return url.protocol === "http:" && ["localhost", "127.0.0.1", "[::1]"].includes(url.hostname);
|
|
@@ -89,6 +89,27 @@ async function portState(url, timeout) {
|
|
|
89
89
|
socket.once("error", (error) => finish(error.code === "ECONNREFUSED" ? "closed" : "unknown"));
|
|
90
90
|
});
|
|
91
91
|
}
|
|
92
|
+
async function localPortAvailable(url, timeout) {
|
|
93
|
+
if (process.platform !== "linux" || !isLocalServer(url.href)) return false;
|
|
94
|
+
const host = url.hostname === "localhost" ? "127.0.0.1" : url.hostname.replace(/^\[|\]$/g, "");
|
|
95
|
+
return new Promise((resolve4) => {
|
|
96
|
+
const server = createServer((socket) => socket.destroy());
|
|
97
|
+
let finished = false;
|
|
98
|
+
const finish = (available) => {
|
|
99
|
+
if (finished) return;
|
|
100
|
+
finished = true;
|
|
101
|
+
clearTimeout(timer);
|
|
102
|
+
resolve4(available);
|
|
103
|
+
};
|
|
104
|
+
const timer = setTimeout(() => {
|
|
105
|
+
server.close();
|
|
106
|
+
finish(false);
|
|
107
|
+
}, timeout);
|
|
108
|
+
server.once("error", () => finish(false));
|
|
109
|
+
server.once("listening", () => server.close(() => finish(true)));
|
|
110
|
+
server.listen({ host, port: Number(url.port || "80"), exclusive: true });
|
|
111
|
+
});
|
|
112
|
+
}
|
|
92
113
|
async function probeService(input, timeout = 1500) {
|
|
93
114
|
const root = normalizeServerUrl(input);
|
|
94
115
|
const url = new URL(root);
|
|
@@ -127,6 +148,7 @@ async function probeService(input, timeout = 1500) {
|
|
|
127
148
|
const state = await portState(url, timeout);
|
|
128
149
|
if (state === "closed") return { kind: "stopped" };
|
|
129
150
|
if (state === "open") return { kind: "unreachable", message: `${root} \u7AEF\u53E3\u5DF2\u5360\u7528\u4F46\u8EAB\u4EFD\u68C0\u67E5\u65E0\u54CD\u5E94\uFF1B\u670D\u52A1\u53EF\u80FD\u6302\u8D77\u3002\u672A\u542F\u52A8\u5176\u4ED6\u670D\u52A1\u3002` };
|
|
151
|
+
if (await localPortAvailable(url, timeout)) return { kind: "stopped" };
|
|
130
152
|
return { kind: "unreachable", message: `\u65E0\u6CD5\u8BBF\u95EE ${root}\uFF0C\u8BF7\u68C0\u67E5\u7F51\u7EDC\u3001\u5730\u5740\u6216\u8F6C\u53D1\u914D\u7F6E\u3002` };
|
|
131
153
|
}
|
|
132
154
|
}
|
|
@@ -307,7 +329,7 @@ async function main() {
|
|
|
307
329
|
return;
|
|
308
330
|
}
|
|
309
331
|
if (action === "install-vscode") {
|
|
310
|
-
const { installVSCodeExtension } = await import("./vscodeInstaller-
|
|
332
|
+
const { installVSCodeExtension } = await import("./vscodeInstaller-CNVZA65C.js");
|
|
311
333
|
await installVSCodeExtension({ vsixPath: values.vsix, onInstalled: (result) => console.log(`${result.target} \u5DF2\u5B89\u88C5 ${result.extension}`) });
|
|
312
334
|
console.log("\u8BF7\u5728\u5DF2\u6253\u5F00\u7684 VS Code \u7A97\u53E3\u8FD0\u884C Developer: Reload Window \u4EE5\u52A0\u8F7D\u63D2\u4EF6\u3002");
|
|
313
335
|
return;
|
|
@@ -333,7 +355,7 @@ async function main() {
|
|
|
333
355
|
config.host = new URL(url).hostname === "localhost" ? "127.0.0.1" : new URL(url).hostname.replace(/^\[|\]$/g, "");
|
|
334
356
|
config.port = Number(new URL(url).port || 80);
|
|
335
357
|
const instanceId = randomUUID2();
|
|
336
|
-
const { createApp } = await import("./app-
|
|
358
|
+
const { createApp } = await import("./app-GCOLVKOP.js");
|
|
337
359
|
const runtime = await createApp(config, { managed: true, instanceId, staticDir: fileURLToPath(new URL("../dist/", import.meta.url)) });
|
|
338
360
|
const stamp = await processStamp(process.pid);
|
|
339
361
|
if (!stamp) throw new Error("\u65E0\u6CD5\u53D6\u5F97\u8FDB\u7A0B\u542F\u52A8\u6807\u8BC6\uFF0C\u62D2\u7EDD\u542F\u52A8\u4E0D\u53EF\u5B89\u5168\u7BA1\u7406\u7684\u540E\u53F0");
|
package/package.json
CHANGED
|
Binary file
|