v0.13.5 web ui updates
test / test (push) Canceled after 0s

This commit is contained in:
lixen committed 2026-10-15 22:02:30 -04:00
1 parent caf30df968
commit 87dcb3e550
13 files changed
+333 -156

No files matched your search

+6 -2
View File
@@ -79,18 +79,22 @@ wasm:
@echo "Built WASM client: $(WASM_BINARY)" @echo "Built WASM client: $(WASM_BINARY)"
@echo "Size: $$(du -h $(WASM_BINARY) | cut -f1)" @echo "Size: $$(du -h $(WASM_BINARY) | cut -f1)"
# Download xterm.js and all addons # Download xterm.js, its addons and licence. jsDelivr's header comment and the
# trailing sourceMappingURL, to a map no one ships, are stripped: the files
# are then the ones vif's web/vendor/ and lixen.com serve.
.PHONY: wasm-deps .PHONY: wasm-deps
wasm-deps: wasm-deps:
@echo "Downloading xterm.js $(XTERM_VERSION) and addons..." @echo "Downloading xterm.js $(XTERM_VERSION) and addons..."
@mkdir -p $(WASM_LIB_DIR) @mkdir -p $(WASM_LIB_DIR)
@cd $(WASM_LIB_DIR) && \ @cd $(WASM_LIB_DIR) && \
$(DOWNLOAD) https://cdn.jsdelivr.net/npm/@xterm/xterm@$(XTERM_VERSION)/LICENSE && \
$(DOWNLOAD) https://cdn.jsdelivr.net/npm/@xterm/xterm@$(XTERM_VERSION)/lib/xterm.min.js && \ $(DOWNLOAD) https://cdn.jsdelivr.net/npm/@xterm/xterm@$(XTERM_VERSION)/lib/xterm.min.js && \
$(DOWNLOAD) https://cdn.jsdelivr.net/npm/@xterm/xterm@$(XTERM_VERSION)/css/xterm.min.css && \ $(DOWNLOAD) https://cdn.jsdelivr.net/npm/@xterm/xterm@$(XTERM_VERSION)/css/xterm.min.css && \
$(DOWNLOAD) https://cdn.jsdelivr.net/npm/@xterm/addon-fit@$(XTERM_FIT_VERSION)/lib/addon-fit.min.js && \ $(DOWNLOAD) https://cdn.jsdelivr.net/npm/@xterm/addon-fit@$(XTERM_FIT_VERSION)/lib/addon-fit.min.js && \
$(DOWNLOAD) https://cdn.jsdelivr.net/npm/@xterm/addon-webgl@$(XTERM_WEBGL_VERSION)/lib/addon-webgl.min.js && \ $(DOWNLOAD) https://cdn.jsdelivr.net/npm/@xterm/addon-webgl@$(XTERM_WEBGL_VERSION)/lib/addon-webgl.min.js && \
$(DOWNLOAD) https://cdn.jsdelivr.net/npm/@xterm/addon-web-links@$(XTERM_LINKS_VERSION)/lib/addon-web-links.min.js && \ $(DOWNLOAD) https://cdn.jsdelivr.net/npm/@xterm/addon-web-links@$(XTERM_LINKS_VERSION)/lib/addon-web-links.min.js && \
$(DOWNLOAD) https://cdn.jsdelivr.net/npm/@xterm/addon-unicode11@$(XTERM_UNICODE_VERSION)/lib/addon-unicode11.min.js $(DOWNLOAD) https://cdn.jsdelivr.net/npm/@xterm/addon-unicode11@$(XTERM_UNICODE_VERSION)/lib/addon-unicode11.min.js && \
for f in *.min.js *.min.css; do sed -e '1,/^ \*\/$$/d' -e '$$d' "$$f" > "$$f.tmp" && mv "$$f.tmp" "$$f"; done
@echo "Downloaded to $(WASM_LIB_DIR)/" @echo "Downloaded to $(WASM_LIB_DIR)/"
@ls -la $(WASM_LIB_DIR)/ @ls -la $(WASM_LIB_DIR)/
+6 -3
View File
@@ -212,9 +212,12 @@ server's API paths:
API base from its script element, `<script src="app.js" data-api="…">`, API base from its script element, `<script src="app.js" data-api="…">`,
which the embedded server sets from `-web-api-url`; without one, as copied, which the embedded server sets from `-web-api-url`; without one, as copied,
it uses the `/chess` API prefix. it uses the `/chess` API prefix.
- **WASM terminal client (if published):** `make wasm` (xterm.js is committed - **WASM terminal client (if published):** `make wasm` (xterm.js and its
under `lib/`), then copy `web/chess-client-wasm/`. It derives its API base licence are committed under `lib/`), then copy `web/chess-client-wasm/`.
as `<origin>/chess`. Its API paths are compiled into `chess-client.wasm`, `terminal.js` runs the client in the page's `#chess-terminal`, whose
`data-wasm-url` names the binary; a site with a page of its own loads it
into the same markup (`index.html`). The client derives its API base as
`<origin>/chess`. Its API paths are compiled into `chess-client.wasm`,
so rebuild it whenever `internal/client/api` changes; publish it together so rebuild it whenever `internal/client/api` changes; publish it together
with the `wasm_exec.js` that `make wasm` copies from the same Go toolchain. with the `wasm_exec.js` that `make wasm` copies from the same Go toolchain.
@@ -46,7 +46,7 @@
</div> </div>
<div class="controls"> <div class="controls">
<button id="new-game-btn" class="btn btn-primary">New Game</button> <button id="new-game-btn" class="btn btn-primary">New</button>
<button id="undo-btn" class="btn btn-secondary" disabled>Undo</button> <button id="undo-btn" class="btn btn-secondary" disabled>Undo</button>
<button id="draw-btn" class="btn btn-secondary" title="Offer a draw" disabled>Draw</button> <button id="draw-btn" class="btn btn-secondary" title="Offer a draw" disabled>Draw</button>
<button id="resign-btn" class="btn btn-secondary" title="Resign this game" disabled>Resign</button> <button id="resign-btn" class="btn btn-secondary" title="Resign this game" disabled>Resign</button>
+7 -4
View File
@@ -8,13 +8,16 @@
<link rel="stylesheet" href="terminal.css"> <link rel="stylesheet" href="terminal.css">
</head> </head>
<body> <body>
<div id="terminal"></div> <div class="chess-terminal" id="chess-terminal" data-wasm-url="chess-client.wasm">
<div class="chess-terminal-screen" id="chess-terminal-screen"></div>
<p class="chess-terminal-status" id="chess-terminal-status" role="status">
<span id="chess-terminal-state">Loading the client…</span><span class="chess-terminal-progress" id="chess-terminal-progress" aria-hidden="true"></span>
</p>
</div>
<script src="lib/xterm.min.js"></script> <script src="lib/xterm.min.js"></script>
<script src="lib/addon-fit.min.js"></script> <script src="lib/addon-fit.min.js"></script>
<script src="lib/addon-webgl.min.js"></script> <script src="lib/addon-webgl.min.js"></script>
<script src="lib/addon-web-links.min.js"></script>
<script src="lib/addon-unicode11.min.js"></script>
<script src="wasm_exec.js"></script> <script src="wasm_exec.js"></script>
<script src="terminal.js"></script> <script src="terminal.js"></script>
</body> </body>
</html>> </html>
+21
View File
@@ -0,0 +1,21 @@
Copyright (c) 2017-2019, The xterm.js authors (https://github.com/xtermjs/xterm.js)
Copyright (c) 2014-2016, SourceLair Private Company (https://www.sourcelair.com)
Copyright (c) 2012-2013, Christopher Jeffrey (https://github.com/chjj/)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-7
View File
@@ -1,8 +1 @@
/**
* Skipped minification because the original files appears to be already minified.
* Original file: /npm/@xterm/addon-fit@0.10.0/lib/addon-fit.js
*
* Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
*/
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.FitAddon=t():e.FitAddon=t()}(self,(()=>(()=>{"use strict";var e={};return(()=>{var t=e;Object.defineProperty(t,"__esModule",{value:!0}),t.FitAddon=void 0,t.FitAddon=class{activate(e){this._terminal=e}dispose(){}fit(){const e=this.proposeDimensions();if(!e||!this._terminal||isNaN(e.cols)||isNaN(e.rows))return;const t=this._terminal._core;this._terminal.rows===e.rows&&this._terminal.cols===e.cols||(t._renderService.clear(),this._terminal.resize(e.cols,e.rows))}proposeDimensions(){if(!this._terminal)return;if(!this._terminal.element||!this._terminal.element.parentElement)return;const e=this._terminal._core,t=e._renderService.dimensions;if(0===t.css.cell.width||0===t.css.cell.height)return;const r=0===this._terminal.options.scrollback?0:e.viewport.scrollBarWidth,i=window.getComputedStyle(this._terminal.element.parentElement),o=parseInt(i.getPropertyValue("height")),s=Math.max(0,parseInt(i.getPropertyValue("width"))),n=window.getComputedStyle(this._terminal.element),l=o-(parseInt(n.getPropertyValue("padding-top"))+parseInt(n.getPropertyValue("padding-bottom"))),a=s-(parseInt(n.getPropertyValue("padding-right"))+parseInt(n.getPropertyValue("padding-left")))-r;return{cols:Math.max(2,Math.floor(a/t.css.cell.width)),rows:Math.max(1,Math.floor(l/t.css.cell.height))}}}})(),e})())); !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.FitAddon=t():e.FitAddon=t()}(self,(()=>(()=>{"use strict";var e={};return(()=>{var t=e;Object.defineProperty(t,"__esModule",{value:!0}),t.FitAddon=void 0,t.FitAddon=class{activate(e){this._terminal=e}dispose(){}fit(){const e=this.proposeDimensions();if(!e||!this._terminal||isNaN(e.cols)||isNaN(e.rows))return;const t=this._terminal._core;this._terminal.rows===e.rows&&this._terminal.cols===e.cols||(t._renderService.clear(),this._terminal.resize(e.cols,e.rows))}proposeDimensions(){if(!this._terminal)return;if(!this._terminal.element||!this._terminal.element.parentElement)return;const e=this._terminal._core,t=e._renderService.dimensions;if(0===t.css.cell.width||0===t.css.cell.height)return;const r=0===this._terminal.options.scrollback?0:e.viewport.scrollBarWidth,i=window.getComputedStyle(this._terminal.element.parentElement),o=parseInt(i.getPropertyValue("height")),s=Math.max(0,parseInt(i.getPropertyValue("width"))),n=window.getComputedStyle(this._terminal.element),l=o-(parseInt(n.getPropertyValue("padding-top"))+parseInt(n.getPropertyValue("padding-bottom"))),a=s-(parseInt(n.getPropertyValue("padding-right"))+parseInt(n.getPropertyValue("padding-left")))-r;return{cols:Math.max(2,Math.floor(a/t.css.cell.width)),rows:Math.max(1,Math.floor(l/t.css.cell.height))}}}})(),e})()));
//# sourceMappingURL=addon-fit.js.map
-7
View File
@@ -1,8 +1 @@
/**
* Skipped minification because the original files appears to be already minified.
* Original file: /npm/@xterm/addon-unicode11@0.8.0/lib/addon-unicode11.js
*
* Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
*/
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.Unicode11Addon=t():e.Unicode11Addon=t()}(this,(()=>(()=>{"use strict";var e={433:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.UnicodeV11=void 0;const r=i(938),s=[[768,879],[1155,1161],[1425,1469],[1471,1471],[1473,1474],[1476,1477],[1479,1479],[1536,1541],[1552,1562],[1564,1564],[1611,1631],[1648,1648],[1750,1757],[1759,1764],[1767,1768],[1770,1773],[1807,1807],[1809,1809],[1840,1866],[1958,1968],[2027,2035],[2045,2045],[2070,2073],[2075,2083],[2085,2087],[2089,2093],[2137,2139],[2259,2306],[2362,2362],[2364,2364],[2369,2376],[2381,2381],[2385,2391],[2402,2403],[2433,2433],[2492,2492],[2497,2500],[2509,2509],[2530,2531],[2558,2558],[2561,2562],[2620,2620],[2625,2626],[2631,2632],[2635,2637],[2641,2641],[2672,2673],[2677,2677],[2689,2690],[2748,2748],[2753,2757],[2759,2760],[2765,2765],[2786,2787],[2810,2815],[2817,2817],[2876,2876],[2879,2879],[2881,2884],[2893,2893],[2902,2902],[2914,2915],[2946,2946],[3008,3008],[3021,3021],[3072,3072],[3076,3076],[3134,3136],[3142,3144],[3146,3149],[3157,3158],[3170,3171],[3201,3201],[3260,3260],[3263,3263],[3270,3270],[3276,3277],[3298,3299],[3328,3329],[3387,3388],[3393,3396],[3405,3405],[3426,3427],[3530,3530],[3538,3540],[3542,3542],[3633,3633],[3636,3642],[3655,3662],[3761,3761],[3764,3772],[3784,3789],[3864,3865],[3893,3893],[3895,3895],[3897,3897],[3953,3966],[3968,3972],[3974,3975],[3981,3991],[3993,4028],[4038,4038],[4141,4144],[4146,4151],[4153,4154],[4157,4158],[4184,4185],[4190,4192],[4209,4212],[4226,4226],[4229,4230],[4237,4237],[4253,4253],[4448,4607],[4957,4959],[5906,5908],[5938,5940],[5970,5971],[6002,6003],[6068,6069],[6071,6077],[6086,6086],[6089,6099],[6109,6109],[6155,6158],[6277,6278],[6313,6313],[6432,6434],[6439,6440],[6450,6450],[6457,6459],[6679,6680],[6683,6683],[6742,6742],[6744,6750],[6752,6752],[6754,6754],[6757,6764],[6771,6780],[6783,6783],[6832,6846],[6912,6915],[6964,6964],[6966,6970],[6972,6972],[6978,6978],[7019,7027],[7040,7041],[7074,7077],[7080,7081],[7083,7085],[7142,7142],[7144,7145],[7149,7149],[7151,7153],[7212,7219],[7222,7223],[7376,7378],[7380,7392],[7394,7400],[7405,7405],[7412,7412],[7416,7417],[7616,7673],[7675,7679],[8203,8207],[8234,8238],[8288,8292],[8294,8303],[8400,8432],[11503,11505],[11647,11647],[11744,11775],[12330,12333],[12441,12442],[42607,42610],[42612,42621],[42654,42655],[42736,42737],[43010,43010],[43014,43014],[43019,43019],[43045,43046],[43204,43205],[43232,43249],[43263,43263],[43302,43309],[43335,43345],[43392,43394],[43443,43443],[43446,43449],[43452,43453],[43493,43493],[43561,43566],[43569,43570],[43573,43574],[43587,43587],[43596,43596],[43644,43644],[43696,43696],[43698,43700],[43703,43704],[43710,43711],[43713,43713],[43756,43757],[43766,43766],[44005,44005],[44008,44008],[44013,44013],[64286,64286],[65024,65039],[65056,65071],[65279,65279],[65529,65531]],n=[[66045,66045],[66272,66272],[66422,66426],[68097,68099],[68101,68102],[68108,68111],[68152,68154],[68159,68159],[68325,68326],[68900,68903],[69446,69456],[69633,69633],[69688,69702],[69759,69761],[69811,69814],[69817,69818],[69821,69821],[69837,69837],[69888,69890],[69927,69931],[69933,69940],[70003,70003],[70016,70017],[70070,70078],[70089,70092],[70191,70193],[70196,70196],[70198,70199],[70206,70206],[70367,70367],[70371,70378],[70400,70401],[70459,70460],[70464,70464],[70502,70508],[70512,70516],[70712,70719],[70722,70724],[70726,70726],[70750,70750],[70835,70840],[70842,70842],[70847,70848],[70850,70851],[71090,71093],[71100,71101],[71103,71104],[71132,71133],[71219,71226],[71229,71229],[71231,71232],[71339,71339],[71341,71341],[71344,71349],[71351,71351],[71453,71455],[71458,71461],[71463,71467],[71727,71735],[71737,71738],[72148,72151],[72154,72155],[72160,72160],[72193,72202],[72243,72248],[72251,72254],[72263,72263],[72273,72278],[72281,72283],[72330,72342],[72344,72345],[72752,72758],[72760,72765],[72767,72767],[72850,72871],[72874,72880],[72882,72883],[72885,72886],[73009,73014],[73018,73018],[73020,73021],[73023,73029],[73031,73031],[73104,73105],[73109,73109],[73111,73111],[73459,73460],[78896,78904],[92912,92916],[92976,92982],[94031,94031],[94095,94098],[113821,113822],[113824,113827],[119143,119145],[119155,119170],[119173,119179],[119210,119213],[119362,119364],[121344,121398],[121403,121452],[121461,121461],[121476,121476],[121499,121503],[121505,121519],[122880,122886],[122888,122904],[122907,122913],[122915,122916],[122918,122922],[123184,123190],[123628,123631],[125136,125142],[125252,125258],[917505,917505],[917536,917631],[917760,917999]],o=[[4352,4447],[8986,8987],[9001,9002],[9193,9196],[9200,9200],[9203,9203],[9725,9726],[9748,9749],[9800,9811],[9855,9855],[9875,9875],[9889,9889],[9898,9899],[9917,9918],[9924,9925],[9934,9934],[9940,9940],[9962,9962],[9970,9971],[9973,9973],[9978,9978],[9981,9981],[9989,9989],[9994,9995],[10024,10024],[Line truncated !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.Unicode11Addon=t():e.Unicode11Addon=t()}(this,(()=>(()=>{"use strict";var e={433:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.UnicodeV11=void 0;const r=i(938),s=[[768,879],[1155,1161],[1425,1469],[1471,1471],[1473,1474],[1476,1477],[1479,1479],[1536,1541],[1552,1562],[1564,1564],[1611,1631],[1648,1648],[1750,1757],[1759,1764],[1767,1768],[1770,1773],[1807,1807],[1809,1809],[1840,1866],[1958,1968],[2027,2035],[2045,2045],[2070,2073],[2075,2083],[2085,2087],[2089,2093],[2137,2139],[2259,2306],[2362,2362],[2364,2364],[2369,2376],[2381,2381],[2385,2391],[2402,2403],[2433,2433],[2492,2492],[2497,2500],[2509,2509],[2530,2531],[2558,2558],[2561,2562],[2620,2620],[2625,2626],[2631,2632],[2635,2637],[2641,2641],[2672,2673],[2677,2677],[2689,2690],[2748,2748],[2753,2757],[2759,2760],[2765,2765],[2786,2787],[2810,2815],[2817,2817],[2876,2876],[2879,2879],[2881,2884],[2893,2893],[2902,2902],[2914,2915],[2946,2946],[3008,3008],[3021,3021],[3072,3072],[3076,3076],[3134,3136],[3142,3144],[3146,3149],[3157,3158],[3170,3171],[3201,3201],[3260,3260],[3263,3263],[3270,3270],[3276,3277],[3298,3299],[3328,3329],[3387,3388],[3393,3396],[3405,3405],[3426,3427],[3530,3530],[3538,3540],[3542,3542],[3633,3633],[3636,3642],[3655,3662],[3761,3761],[3764,3772],[3784,3789],[3864,3865],[3893,3893],[3895,3895],[3897,3897],[3953,3966],[3968,3972],[3974,3975],[3981,3991],[3993,4028],[4038,4038],[4141,4144],[4146,4151],[4153,4154],[4157,4158],[4184,4185],[4190,4192],[4209,4212],[4226,4226],[4229,4230],[4237,4237],[4253,4253],[4448,4607],[4957,4959],[5906,5908],[5938,5940],[5970,5971],[6002,6003],[6068,6069],[6071,6077],[6086,6086],[6089,6099],[6109,6109],[6155,6158],[6277,6278],[6313,6313],[6432,6434],[6439,6440],[6450,6450],[6457,6459],[6679,6680],[6683,6683],[6742,6742],[6744,6750],[6752,6752],[6754,6754],[6757,6764],[6771,6780],[6783,6783],[6832,6846],[6912,6915],[6964,6964],[6966,6970],[6972,6972],[6978,6978],[7019,7027],[7040,7041],[7074,7077],[7080,7081],[7083,7085],[7142,7142],[7144,7145],[7149,7149],[7151,7153],[7212,7219],[7222,7223],[7376,7378],[7380,7392],[7394,7400],[7405,7405],[7412,7412],[7416,7417],[7616,7673],[7675,7679],[8203,8207],[8234,8238],[8288,8292],[8294,8303],[8400,8432],[11503,11505],[11647,11647],[11744,11775],[12330,12333],[12441,12442],[42607,42610],[42612,42621],[42654,42655],[42736,42737],[43010,43010],[43014,43014],[43019,43019],[43045,43046],[43204,43205],[43232,43249],[43263,43263],[43302,43309],[43335,43345],[43392,43394],[43443,43443],[43446,43449],[43452,43453],[43493,43493],[43561,43566],[43569,43570],[43573,43574],[43587,43587],[43596,43596],[43644,43644],[43696,43696],[43698,43700],[43703,43704],[43710,43711],[43713,43713],[43756,43757],[43766,43766],[44005,44005],[44008,44008],[44013,44013],[64286,64286],[65024,65039],[65056,65071],[65279,65279],[65529,65531]],n=[[66045,66045],[66272,66272],[66422,66426],[68097,68099],[68101,68102],[68108,68111],[68152,68154],[68159,68159],[68325,68326],[68900,68903],[69446,69456],[69633,69633],[69688,69702],[69759,69761],[69811,69814],[69817,69818],[69821,69821],[69837,69837],[69888,69890],[69927,69931],[69933,69940],[70003,70003],[70016,70017],[70070,70078],[70089,70092],[70191,70193],[70196,70196],[70198,70199],[70206,70206],[70367,70367],[70371,70378],[70400,70401],[70459,70460],[70464,70464],[70502,70508],[70512,70516],[70712,70719],[70722,70724],[70726,70726],[70750,70750],[70835,70840],[70842,70842],[70847,70848],[70850,70851],[71090,71093],[71100,71101],[71103,71104],[71132,71133],[71219,71226],[71229,71229],[71231,71232],[71339,71339],[71341,71341],[71344,71349],[71351,71351],[71453,71455],[71458,71461],[71463,71467],[71727,71735],[71737,71738],[72148,72151],[72154,72155],[72160,72160],[72193,72202],[72243,72248],[72251,72254],[72263,72263],[72273,72278],[72281,72283],[72330,72342],[72344,72345],[72752,72758],[72760,72765],[72767,72767],[72850,72871],[72874,72880],[72882,72883],[72885,72886],[73009,73014],[73018,73018],[73020,73021],[73023,73029],[73031,73031],[73104,73105],[73109,73109],[73111,73111],[73459,73460],[78896,78904],[92912,92916],[92976,92982],[94031,94031],[94095,94098],[113821,113822],[113824,113827],[119143,119145],[119155,119170],[119173,119179],[119210,119213],[119362,119364],[121344,121398],[121403,121452],[121461,121461],[121476,121476],[121499,121503],[121505,121519],[122880,122886],[122888,122904],[122907,122913],[122915,122916],[122918,122922],[123184,123190],[123628,123631],[125136,125142],[125252,125258],[917505,917505],[917536,917631],[917760,917999]],o=[[4352,4447],[8986,8987],[9001,9002],[9193,9196],[9200,9200],[9203,9203],[9725,9726],[9748,9749],[9800,9811],[9855,9855],[9875,9875],[9889,9889],[9898,9899],[9917,9918],[9924,9925],[9934,9934],[9940,9940],[9962,9962],[9970,9971],[9973,9973],[9978,9978],[9981,9981],[9989,9989],[9994,9995],[10024,10024],[Line truncated
//# sourceMappingURL=addon-unicode11.js.map
-7
View File
@@ -1,8 +1 @@
/**
* Skipped minification because the original files appears to be already minified.
* Original file: /npm/@xterm/addon-web-links@0.11.0/lib/addon-web-links.js
*
* Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
*/
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.WebLinksAddon=t():e.WebLinksAddon=t()}(self,(()=>(()=>{"use strict";var e={6:(e,t)=>{function n(e){try{const t=new URL(e),n=t.password&&t.username?`${t.protocol}//${t.username}:${t.password}@${t.host}`:t.username?`${t.protocol}//${t.username}@${t.host}`:`${t.protocol}//${t.host}`;return e.toLocaleLowerCase().startsWith(n.toLocaleLowerCase())}catch(e){return!1}}Object.defineProperty(t,"__esModule",{value:!0}),t.LinkComputer=t.WebLinkProvider=void 0,t.WebLinkProvider=class{constructor(e,t,n,o={}){this._terminal=e,this._regex=t,this._handler=n,this._options=o}provideLinks(e,t){const n=o.computeLink(e,this._regex,this._terminal,this._handler);t(this._addCallbacks(n))}_addCallbacks(e){return e.map((e=>(e.leave=this._options.leave,e.hover=(t,n)=>{if(this._options.hover){const{range:o}=e;this._options.hover(t,n,o)}},e)))}};class o{static computeLink(e,t,r,i){const s=new RegExp(t.source,(t.flags||"")+"g"),[a,c]=o._getWindowedLineStrings(e-1,r),l=a.join("");let d;const p=[];for(;d=s.exec(l);){const e=d[0];if(!n(e))continue;const[t,s]=o._mapStrIdx(r,c,0,d.index),[a,l]=o._mapStrIdx(r,t,s,e.length);if(-1===t||-1===s||-1===a||-1===l)continue;const h={start:{x:s+1,y:t+1},end:{x:l,y:a+1}};p.push({range:h,text:e,activate:i})}return p}static _getWindowedLineStrings(e,t){let n,o=e,r=e,i=0,s="";const a=[];if(n=t.buffer.active.getLine(e)){const e=n.translateToString(!0);if(n.isWrapped&&" "!==e[0]){for(i=0;(n=t.buffer.active.getLine(--o))&&i<2048&&(s=n.translateToString(!0),i+=s.length,a.push(s),n.isWrapped&&-1===s.indexOf(" ")););a.reverse()}for(a.push(e),i=0;(n=t.buffer.active.getLine(++r))&&n.isWrapped&&i<2048&&(s=n.translateToString(!0),i+=s.length,a.push(s),-1===s.indexOf(" ")););}return[a,o]}static _mapStrIdx(e,t,n,o){const r=e.buffer.active,i=r.getNullCell();let s=n;for(;o;){const e=r.getLine(t);if(!e)return[-1,-1];for(let n=s;n<e.length;++n){e.getCell(n,i);const s=i.getChars();if(i.getWidth()&&(o-=s.length||1,n===e.length-1&&""===s)){const e=r.getLine(t+1);e&&e.isWrapped&&(e.getCell(0,i),2===i.getWidth()&&(o+=1))}if(o<0)return[t,n]}t++,s=0}return[t,s]}}t.LinkComputer=o}},t={};function n(o){var r=t[o];if(void 0!==r)return r.exports;var i=t[o]={exports:{}};return e[o](i,i.exports,n),i.exports}var o={};return(()=>{var e=o;Object.defineProperty(e,"__esModule",{value:!0}),e.WebLinksAddon=void 0;const t=n(6),r=/(https?|HTTPS?):[/]{2}[^\s"'!*(){}|\\\^<>`]*[^\s"':,.!?{}|\\\^~\[\]`()<>]/;function i(e,t){const n=window.open();if(n){try{n.opener=null}catch{}n.location.href=t}else console.warn("Opening link blocked as opener could not be cleared")}e.WebLinksAddon=class{constructor(e=i,t={}){this._handler=e,this._options=t}activate(e){this._terminal=e;const n=this._options,o=n.urlRegex||r;this._linkProvider=this._terminal.registerLinkProvider(new t.WebLinkProvider(this._terminal,o,this._handler,n))}dispose(){this._linkProvider?.dispose()}}})(),o})())); !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.WebLinksAddon=t():e.WebLinksAddon=t()}(self,(()=>(()=>{"use strict";var e={6:(e,t)=>{function n(e){try{const t=new URL(e),n=t.password&&t.username?`${t.protocol}//${t.username}:${t.password}@${t.host}`:t.username?`${t.protocol}//${t.username}@${t.host}`:`${t.protocol}//${t.host}`;return e.toLocaleLowerCase().startsWith(n.toLocaleLowerCase())}catch(e){return!1}}Object.defineProperty(t,"__esModule",{value:!0}),t.LinkComputer=t.WebLinkProvider=void 0,t.WebLinkProvider=class{constructor(e,t,n,o={}){this._terminal=e,this._regex=t,this._handler=n,this._options=o}provideLinks(e,t){const n=o.computeLink(e,this._regex,this._terminal,this._handler);t(this._addCallbacks(n))}_addCallbacks(e){return e.map((e=>(e.leave=this._options.leave,e.hover=(t,n)=>{if(this._options.hover){const{range:o}=e;this._options.hover(t,n,o)}},e)))}};class o{static computeLink(e,t,r,i){const s=new RegExp(t.source,(t.flags||"")+"g"),[a,c]=o._getWindowedLineStrings(e-1,r),l=a.join("");let d;const p=[];for(;d=s.exec(l);){const e=d[0];if(!n(e))continue;const[t,s]=o._mapStrIdx(r,c,0,d.index),[a,l]=o._mapStrIdx(r,t,s,e.length);if(-1===t||-1===s||-1===a||-1===l)continue;const h={start:{x:s+1,y:t+1},end:{x:l,y:a+1}};p.push({range:h,text:e,activate:i})}return p}static _getWindowedLineStrings(e,t){let n,o=e,r=e,i=0,s="";const a=[];if(n=t.buffer.active.getLine(e)){const e=n.translateToString(!0);if(n.isWrapped&&" "!==e[0]){for(i=0;(n=t.buffer.active.getLine(--o))&&i<2048&&(s=n.translateToString(!0),i+=s.length,a.push(s),n.isWrapped&&-1===s.indexOf(" ")););a.reverse()}for(a.push(e),i=0;(n=t.buffer.active.getLine(++r))&&n.isWrapped&&i<2048&&(s=n.translateToString(!0),i+=s.length,a.push(s),-1===s.indexOf(" ")););}return[a,o]}static _mapStrIdx(e,t,n,o){const r=e.buffer.active,i=r.getNullCell();let s=n;for(;o;){const e=r.getLine(t);if(!e)return[-1,-1];for(let n=s;n<e.length;++n){e.getCell(n,i);const s=i.getChars();if(i.getWidth()&&(o-=s.length||1,n===e.length-1&&""===s)){const e=r.getLine(t+1);e&&e.isWrapped&&(e.getCell(0,i),2===i.getWidth()&&(o+=1))}if(o<0)return[t,n]}t++,s=0}return[t,s]}}t.LinkComputer=o}},t={};function n(o){var r=t[o];if(void 0!==r)return r.exports;var i=t[o]={exports:{}};return e[o](i,i.exports,n),i.exports}var o={};return(()=>{var e=o;Object.defineProperty(e,"__esModule",{value:!0}),e.WebLinksAddon=void 0;const t=n(6),r=/(https?|HTTPS?):[/]{2}[^\s"'!*(){}|\\\^<>`]*[^\s"':,.!?{}|\\\^~\[\]`()<>]/;function i(e,t){const n=window.open();if(n){try{n.opener=null}catch{}n.location.href=t}else console.warn("Opening link blocked as opener could not be cleared")}e.WebLinksAddon=class{constructor(e=i,t={}){this._handler=e,this._options=t}activate(e){this._terminal=e;const n=this._options,o=n.urlRegex||r;this._linkProvider=this._terminal.registerLinkProvider(new t.WebLinkProvider(this._terminal,o,this._handler,n))}dispose(){this._linkProvider?.dispose()}}})(),o})()));
//# sourceMappingURL=addon-web-links.js.map
-7
View File
@@ -1,8 +1 @@
/**
* Skipped minification because the original files appears to be already minified.
* Original file: /npm/@xterm/addon-webgl@0.18.0/lib/addon-webgl.js
*
* Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
*/
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.WebglAddon=t():e.WebglAddon=t()}(self,(()=>(()=>{"use strict";var e={965:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.GlyphRenderer=void 0;const s=i(374),r=i(509),o=i(855),n=i(859),a=i(381),h=11,l=h*Float32Array.BYTES_PER_ELEMENT;let c,d=0,_=0,u=0;class g extends n.Disposable{constructor(e,t,i,o){super(),this._terminal=e,this._gl=t,this._dimensions=i,this._optionsService=o,this._activeBuffer=0,this._vertices={count:0,attributes:new Float32Array(0),attributesBuffers:[new Float32Array(0),new Float32Array(0)]};const h=this._gl;void 0===r.TextureAtlas.maxAtlasPages&&(r.TextureAtlas.maxAtlasPages=Math.min(32,(0,s.throwIfFalsy)(h.getParameter(h.MAX_TEXTURE_IMAGE_UNITS))),r.TextureAtlas.maxTextureSize=(0,s.throwIfFalsy)(h.getParameter(h.MAX_TEXTURE_SIZE))),this._program=(0,s.throwIfFalsy)((0,a.createProgram)(h,"#version 300 es\nlayout (location = 0) in vec2 a_unitquad;\nlayout (location = 1) in vec2 a_cellpos;\nlayout (location = 2) in vec2 a_offset;\nlayout (location = 3) in vec2 a_size;\nlayout (location = 4) in float a_texpage;\nlayout (location = 5) in vec2 a_texcoord;\nlayout (location = 6) in vec2 a_texsize;\n\nuniform mat4 u_projection;\nuniform vec2 u_resolution;\n\nout vec2 v_texcoord;\nflat out int v_texpage;\n\nvoid main() {\n vec2 zeroToOne = (a_offset / u_resolution) + a_cellpos + (a_unitquad * a_size);\n gl_Position = u_projection * vec4(zeroToOne, 0.0, 1.0);\n v_texpage = int(a_texpage);\n v_texcoord = a_texcoord + a_unitquad * a_texsize;\n}",function(e){let t="";for(let i=1;i<e;i++)t+=` else if (v_texpage == ${i}) { outColor = texture(u_texture[${i}], v_texcoord); }`;return`#version 300 es\nprecision lowp float;\n\nin vec2 v_texcoord;\nflat in int v_texpage;\n\nuniform sampler2D u_texture[${e}];\n\nout vec4 outColor;\n\nvoid main() {\n if (v_texpage == 0) {\n outColor = texture(u_texture[0], v_texcoord);\n } ${t}\n}`}(r.TextureAtlas.maxAtlasPages))),this.register((0,n.toDisposable)((()=>h.deleteProgram(this._program)))),this._projectionLocation=(0,s.throwIfFalsy)(h.getUniformLocation(this._program,"u_projection")),this._resolutionLocation=(0,s.throwIfFalsy)(h.getUniformLocation(this._program,"u_resolution")),this._textureLocation=(0,s.throwIfFalsy)(h.getUniformLocation(this._program,"u_texture")),this._vertexArrayObject=h.createVertexArray(),h.bindVertexArray(this._vertexArrayObject);const c=new Float32Array([0,0,1,0,0,1,1,1]),d=h.createBuffer();this.register((0,n.toDisposable)((()=>h.deleteBuffer(d)))),h.bindBuffer(h.ARRAY_BUFFER,d),h.bufferData(h.ARRAY_BUFFER,c,h.STATIC_DRAW),h.enableVertexAttribArray(0),h.vertexAttribPointer(0,2,this._gl.FLOAT,!1,0,0);const _=new Uint8Array([0,1,2,3]),u=h.createBuffer();this.register((0,n.toDisposable)((()=>h.deleteBuffer(u)))),h.bindBuffer(h.ELEMENT_ARRAY_BUFFER,u),h.bufferData(h.ELEMENT_ARRAY_BUFFER,_,h.STATIC_DRAW),this._attributesBuffer=(0,s.throwIfFalsy)(h.createBuffer()),this.register((0,n.toDisposable)((()=>h.deleteBuffer(this._attributesBuffer)))),h.bindBuffer(h.ARRAY_BUFFER,this._attributesBuffer),h.enableVertexAttribArray(2),h.vertexAttribPointer(2,2,h.FLOAT,!1,l,0),h.vertexAttribDivisor(2,1),h.enableVertexAttribArray(3),h.vertexAttribPointer(3,2,h.FLOAT,!1,l,2*Float32Array.BYTES_PER_ELEMENT),h.vertexAttribDivisor(3,1),h.enableVertexAttribArray(4),h.vertexAttribPointer(4,1,h.FLOAT,!1,l,4*Float32Array.BYTES_PER_ELEMENT),h.vertexAttribDivisor(4,1),h.enableVertexAttribArray(5),h.vertexAttribPointer(5,2,h.FLOAT,!1,l,5*Float32Array.BYTES_PER_ELEMENT),h.vertexAttribDivisor(5,1),h.enableVertexAttribArray(6),h.vertexAttribPointer(6,2,h.FLOAT,!1,l,7*Float32Array.BYTES_PER_ELEMENT),h.vertexAttribDivisor(6,1),h.enableVertexAttribArray(1),h.vertexAttribPointer(1,2,h.FLOAT,!1,l,9*Float32Array.BYTES_PER_ELEMENT),h.vertexAttribDivisor(1,1),h.useProgram(this._program);const g=new Int32Array(r.TextureAtlas.maxAtlasPages);for(let e=0;e<r.TextureAtlas.maxAtlasPages;e++)g[e]=e;h.uniform1iv(this._textureLocation,g),h.uniformMatrix4fv(this._projectionLocation,!1,a.PROJECTION_MATRIX),this._atlasTextures=[];for(let e=0;e<r.TextureAtlas.maxAtlasPages;e++){const t=new a.GLTexture((0,s.throwIfFalsy)(h.createTexture()));this.register((0,n.toDisposable)((()=>h.deleteTexture(t.texture)))),h.activeTexture(h.TEXTURE0+e),h.bindTexture(h.TEXTURE_2D,t.texture),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_WRAP_S,h.CLAMP_TO_EDGE),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_WRAP_T,h.CLAMP_TO_EDGE),h.texImage2D(h.TEXTURE_2D,0,h.RGBA,1,1,0,h.RGBA,h.UNSIGNED_BYTE,new Uint8Array([255,0,0,255])),this._atlasTextures[e]=t}h.enable(h.BLEND),h.blendFunc(h.SRC_ALPHA,h.ONE_MINUS_SRC_ALPHA),this.handleResize()}beginFrame(){return!this._atlas||this._atlas.beginFrame()}updateCell(e,t,i,s,r,o,n,a,h){this._updateCell(this._vertices.attributes,e,t,i,s,r,o,n,a,h)}_updateCell(e,t,i,r,n,a,l,g,v,f){d=(i*this._terminal.cols+t)*h,r!Line truncated !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.WebglAddon=t():e.WebglAddon=t()}(self,(()=>(()=>{"use strict";var e={965:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.GlyphRenderer=void 0;const s=i(374),r=i(509),o=i(855),n=i(859),a=i(381),h=11,l=h*Float32Array.BYTES_PER_ELEMENT;let c,d=0,_=0,u=0;class g extends n.Disposable{constructor(e,t,i,o){super(),this._terminal=e,this._gl=t,this._dimensions=i,this._optionsService=o,this._activeBuffer=0,this._vertices={count:0,attributes:new Float32Array(0),attributesBuffers:[new Float32Array(0),new Float32Array(0)]};const h=this._gl;void 0===r.TextureAtlas.maxAtlasPages&&(r.TextureAtlas.maxAtlasPages=Math.min(32,(0,s.throwIfFalsy)(h.getParameter(h.MAX_TEXTURE_IMAGE_UNITS))),r.TextureAtlas.maxTextureSize=(0,s.throwIfFalsy)(h.getParameter(h.MAX_TEXTURE_SIZE))),this._program=(0,s.throwIfFalsy)((0,a.createProgram)(h,"#version 300 es\nlayout (location = 0) in vec2 a_unitquad;\nlayout (location = 1) in vec2 a_cellpos;\nlayout (location = 2) in vec2 a_offset;\nlayout (location = 3) in vec2 a_size;\nlayout (location = 4) in float a_texpage;\nlayout (location = 5) in vec2 a_texcoord;\nlayout (location = 6) in vec2 a_texsize;\n\nuniform mat4 u_projection;\nuniform vec2 u_resolution;\n\nout vec2 v_texcoord;\nflat out int v_texpage;\n\nvoid main() {\n vec2 zeroToOne = (a_offset / u_resolution) + a_cellpos + (a_unitquad * a_size);\n gl_Position = u_projection * vec4(zeroToOne, 0.0, 1.0);\n v_texpage = int(a_texpage);\n v_texcoord = a_texcoord + a_unitquad * a_texsize;\n}",function(e){let t="";for(let i=1;i<e;i++)t+=` else if (v_texpage == ${i}) { outColor = texture(u_texture[${i}], v_texcoord); }`;return`#version 300 es\nprecision lowp float;\n\nin vec2 v_texcoord;\nflat in int v_texpage;\n\nuniform sampler2D u_texture[${e}];\n\nout vec4 outColor;\n\nvoid main() {\n if (v_texpage == 0) {\n outColor = texture(u_texture[0], v_texcoord);\n } ${t}\n}`}(r.TextureAtlas.maxAtlasPages))),this.register((0,n.toDisposable)((()=>h.deleteProgram(this._program)))),this._projectionLocation=(0,s.throwIfFalsy)(h.getUniformLocation(this._program,"u_projection")),this._resolutionLocation=(0,s.throwIfFalsy)(h.getUniformLocation(this._program,"u_resolution")),this._textureLocation=(0,s.throwIfFalsy)(h.getUniformLocation(this._program,"u_texture")),this._vertexArrayObject=h.createVertexArray(),h.bindVertexArray(this._vertexArrayObject);const c=new Float32Array([0,0,1,0,0,1,1,1]),d=h.createBuffer();this.register((0,n.toDisposable)((()=>h.deleteBuffer(d)))),h.bindBuffer(h.ARRAY_BUFFER,d),h.bufferData(h.ARRAY_BUFFER,c,h.STATIC_DRAW),h.enableVertexAttribArray(0),h.vertexAttribPointer(0,2,this._gl.FLOAT,!1,0,0);const _=new Uint8Array([0,1,2,3]),u=h.createBuffer();this.register((0,n.toDisposable)((()=>h.deleteBuffer(u)))),h.bindBuffer(h.ELEMENT_ARRAY_BUFFER,u),h.bufferData(h.ELEMENT_ARRAY_BUFFER,_,h.STATIC_DRAW),this._attributesBuffer=(0,s.throwIfFalsy)(h.createBuffer()),this.register((0,n.toDisposable)((()=>h.deleteBuffer(this._attributesBuffer)))),h.bindBuffer(h.ARRAY_BUFFER,this._attributesBuffer),h.enableVertexAttribArray(2),h.vertexAttribPointer(2,2,h.FLOAT,!1,l,0),h.vertexAttribDivisor(2,1),h.enableVertexAttribArray(3),h.vertexAttribPointer(3,2,h.FLOAT,!1,l,2*Float32Array.BYTES_PER_ELEMENT),h.vertexAttribDivisor(3,1),h.enableVertexAttribArray(4),h.vertexAttribPointer(4,1,h.FLOAT,!1,l,4*Float32Array.BYTES_PER_ELEMENT),h.vertexAttribDivisor(4,1),h.enableVertexAttribArray(5),h.vertexAttribPointer(5,2,h.FLOAT,!1,l,5*Float32Array.BYTES_PER_ELEMENT),h.vertexAttribDivisor(5,1),h.enableVertexAttribArray(6),h.vertexAttribPointer(6,2,h.FLOAT,!1,l,7*Float32Array.BYTES_PER_ELEMENT),h.vertexAttribDivisor(6,1),h.enableVertexAttribArray(1),h.vertexAttribPointer(1,2,h.FLOAT,!1,l,9*Float32Array.BYTES_PER_ELEMENT),h.vertexAttribDivisor(1,1),h.useProgram(this._program);const g=new Int32Array(r.TextureAtlas.maxAtlasPages);for(let e=0;e<r.TextureAtlas.maxAtlasPages;e++)g[e]=e;h.uniform1iv(this._textureLocation,g),h.uniformMatrix4fv(this._projectionLocation,!1,a.PROJECTION_MATRIX),this._atlasTextures=[];for(let e=0;e<r.TextureAtlas.maxAtlasPages;e++){const t=new a.GLTexture((0,s.throwIfFalsy)(h.createTexture()));this.register((0,n.toDisposable)((()=>h.deleteTexture(t.texture)))),h.activeTexture(h.TEXTURE0+e),h.bindTexture(h.TEXTURE_2D,t.texture),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_WRAP_S,h.CLAMP_TO_EDGE),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_WRAP_T,h.CLAMP_TO_EDGE),h.texImage2D(h.TEXTURE_2D,0,h.RGBA,1,1,0,h.RGBA,h.UNSIGNED_BYTE,new Uint8Array([255,0,0,255])),this._atlasTextures[e]=t}h.enable(h.BLEND),h.blendFunc(h.SRC_ALPHA,h.ONE_MINUS_SRC_ALPHA),this.handleResize()}beginFrame(){return!this._atlas||this._atlas.beginFrame()}updateCell(e,t,i,s,r,o,n,a,h){this._updateCell(this._vertices.attributes,e,t,i,s,r,o,n,a,h)}_updateCell(e,t,i,r,n,a,l,g,v,f){d=(i*this._terminal.cols+t)*h,r!Line truncated
//# sourceMappingURL=addon-webgl.js.map
-7
View File
@@ -1,8 +1 @@
/**
* Minified by jsDelivr using clean-css v5.3.3.
* Original file: /npm/@xterm/xterm@5.5.0/css/xterm.css
*
* Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
*/
.xterm{cursor:text;position:relative;user-select:none;-ms-user-select:none;-webkit-user-select:none}.xterm.focus,.xterm:focus{outline:0}.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;right:0;left:0;top:0;bottom:0}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;left:0;top:0}.xterm .xterm-scroll-area{visibility:hidden}.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;left:0;top:0;bottom:0;right:0;z-index:10;color:transparent;pointer-events:none}.xterm .xterm-accessibility-tree:not(.debug) ::selection{color:transparent}.xterm .xterm-accessibility-tree{user-select:text;white-space:pre}.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{cursor:text;position:relative;user-select:none;-ms-user-select:none;-webkit-user-select:none}.xterm.focus,.xterm:focus{outline:0}.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;right:0;left:0;top:0;bottom:0}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;left:0;top:0}.xterm .xterm-scroll-area{visibility:hidden}.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;left:0;top:0;bottom:0;right:0;z-index:10;color:transparent;pointer-events:none}.xterm .xterm-accessibility-tree:not(.debug) ::selection{color:transparent}.xterm .xterm-accessibility-tree{user-select:text;white-space:pre}.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}
/*# sourceMappingURL=/sm/97377c0c258e109358121823f5790146c714989366481f90e554c42277efb500.map */
-7
View File
@@ -1,8 +1 @@
/**
* Skipped minification because the original files appears to be already minified.
* Original file: /npm/@xterm/xterm@5.5.0/lib/xterm.js
*
* Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
*/
!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var i=t();for(var s in i)("object"==typeof exports?exports:e)[s]=i[s]}}(globalThis,(()=>(()=>{"use strict";var e={4567:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.AccessibilityManager=void 0;const n=i(9042),o=i(9924),a=i(844),h=i(4725),c=i(2585),l=i(3656);let d=t.AccessibilityManager=class extends a.Disposable{constructor(e,t,i,s){super(),this._terminal=e,this._coreBrowserService=i,this._renderService=s,this._rowColumns=new WeakMap,this._liveRegionLineCount=0,this._charsToConsume=[],this._charsToAnnounce="",this._accessibilityContainer=this._coreBrowserService.mainDocument.createElement("div"),this._accessibilityContainer.classList.add("xterm-accessibility"),this._rowContainer=this._coreBrowserService.mainDocument.createElement("div"),this._rowContainer.setAttribute("role","list"),this._rowContainer.classList.add("xterm-accessibility-tree"),this._rowElements=[];for(let e=0;e<this._terminal.rows;e++)this._rowElements[e]=this._createAccessibilityTreeNode(),this._rowContainer.appendChild(this._rowElements[e]);if(this._topBoundaryFocusListener=e=>this._handleBoundaryFocus(e,0),this._bottomBoundaryFocusListener=e=>this._handleBoundaryFocus(e,1),this._rowElements[0].addEventListener("focus",this._topBoundaryFocusListener),this._rowElements[this._rowElements.length-1].addEventListener("focus",this._bottomBoundaryFocusListener),this._refreshRowsDimensions(),this._accessibilityContainer.appendChild(this._rowContainer),this._liveRegion=this._coreBrowserService.mainDocument.createElement("div"),this._liveRegion.classList.add("live-region"),this._liveRegion.setAttribute("aria-live","assertive"),this._accessibilityContainer.appendChild(this._liveRegion),this._liveRegionDebouncer=this.register(new o.TimeBasedDebouncer(this._renderRows.bind(this))),!this._terminal.element)throw new Error("Cannot enable accessibility before Terminal.open");this._terminal.element.insertAdjacentElement("afterbegin",this._accessibilityContainer),this.register(this._terminal.onResize((e=>this._handleResize(e.rows)))),this.register(this._terminal.onRender((e=>this._refreshRows(e.start,e.end)))),this.register(this._terminal.onScroll((()=>this._refreshRows()))),this.register(this._terminal.onA11yChar((e=>this._handleChar(e)))),this.register(this._terminal.onLineFeed((()=>this._handleChar("\n")))),this.register(this._terminal.onA11yTab((e=>this._handleTab(e)))),this.register(this._terminal.onKey((e=>this._handleKey(e.key)))),this.register(this._terminal.onBlur((()=>this._clearLiveRegion()))),this.register(this._renderService.onDimensionsChange((()=>this._refreshRowsDimensions()))),this.register((0,l.addDisposableDomListener)(document,"selectionchange",(()=>this._handleSelectionChange()))),this.register(this._coreBrowserService.onDprChange((()=>this._refreshRowsDimensions()))),this._refreshRows(),this.register((0,a.toDisposable)((()=>{this._accessibilityContainer.remove(),this._rowElements.length=0})))}_handleTab(e){for(let t=0;t<e;t++)this._handleChar(" ")}_handleChar(e){this._liveRegionLineCount<21&&(this._charsToConsume.length>0?this._charsToConsume.shift()!==e&&(this._charsToAnnounce+=e):this._charsToAnnounce+=e,"\n"===e&&(this._liveRegionLineCount++,21===this._liveRegionLineCount&&(this._liveRegion.textContent+=n.tooMuchOutput)))}_clearLiveRegion(){this._liveRegion.textContent="",this._liveRegionLineCount=0}_handleKey(e){this._clearLiveRegion(),/\p{Control}/u.test(e)||this._charsToConsume.push(e)}_refreshRows(e,t){this._liveRegionDebouncer.refresh(e,t,this._terminal.rows)}_renderRows(e,t){const i=this._terminal.buffer,s=i.lines.length.toString();for(let r=e;r<=t;r++){const e=i.lines.get(i.ydisp+r),t=[],n=e?.translateToString(!0,void 0,void 0,t)||"",o=(i.ydisp+r+1).toString(),a=this._rowElements[r];a&&(0===n.length?(a.innerText=" ",this._rowColumns.set(a,[0,1])):(a.textContent=n,this._rowColumns.set(a,t)),a.setAttribute("aria-posinset",o),a.setAttribute("aria-setsize",s))}this._announceCharacters()}_announceCharacters(){0!==this._charsToAnnounce.length&&(this._liveRegion.textContent+=this._charsToAnnounce,this._charsToAnnounce="")}_handleBoundaryFocus(e,t){const i=e.target,s=this._rowElements[0===t?1:this._rowElements.length-2];if(i.getAttribute("aria-posinset")===(0===t?"1":`${this._terminal.buffer.lines.length}`))return;if(e.relatedTarget!==s)return;let r,n;if(0===t?(r=i,n=this._rowElements.pop(),this._rowContainer.removeChild(n)):(r=this._rowElements.shiftLine truncated !function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var i=t();for(var s in i)("object"==typeof exports?exports:e)[s]=i[s]}}(globalThis,(()=>(()=>{"use strict";var e={4567:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.AccessibilityManager=void 0;const n=i(9042),o=i(9924),a=i(844),h=i(4725),c=i(2585),l=i(3656);let d=t.AccessibilityManager=class extends a.Disposable{constructor(e,t,i,s){super(),this._terminal=e,this._coreBrowserService=i,this._renderService=s,this._rowColumns=new WeakMap,this._liveRegionLineCount=0,this._charsToConsume=[],this._charsToAnnounce="",this._accessibilityContainer=this._coreBrowserService.mainDocument.createElement("div"),this._accessibilityContainer.classList.add("xterm-accessibility"),this._rowContainer=this._coreBrowserService.mainDocument.createElement("div"),this._rowContainer.setAttribute("role","list"),this._rowContainer.classList.add("xterm-accessibility-tree"),this._rowElements=[];for(let e=0;e<this._terminal.rows;e++)this._rowElements[e]=this._createAccessibilityTreeNode(),this._rowContainer.appendChild(this._rowElements[e]);if(this._topBoundaryFocusListener=e=>this._handleBoundaryFocus(e,0),this._bottomBoundaryFocusListener=e=>this._handleBoundaryFocus(e,1),this._rowElements[0].addEventListener("focus",this._topBoundaryFocusListener),this._rowElements[this._rowElements.length-1].addEventListener("focus",this._bottomBoundaryFocusListener),this._refreshRowsDimensions(),this._accessibilityContainer.appendChild(this._rowContainer),this._liveRegion=this._coreBrowserService.mainDocument.createElement("div"),this._liveRegion.classList.add("live-region"),this._liveRegion.setAttribute("aria-live","assertive"),this._accessibilityContainer.appendChild(this._liveRegion),this._liveRegionDebouncer=this.register(new o.TimeBasedDebouncer(this._renderRows.bind(this))),!this._terminal.element)throw new Error("Cannot enable accessibility before Terminal.open");this._terminal.element.insertAdjacentElement("afterbegin",this._accessibilityContainer),this.register(this._terminal.onResize((e=>this._handleResize(e.rows)))),this.register(this._terminal.onRender((e=>this._refreshRows(e.start,e.end)))),this.register(this._terminal.onScroll((()=>this._refreshRows()))),this.register(this._terminal.onA11yChar((e=>this._handleChar(e)))),this.register(this._terminal.onLineFeed((()=>this._handleChar("\n")))),this.register(this._terminal.onA11yTab((e=>this._handleTab(e)))),this.register(this._terminal.onKey((e=>this._handleKey(e.key)))),this.register(this._terminal.onBlur((()=>this._clearLiveRegion()))),this.register(this._renderService.onDimensionsChange((()=>this._refreshRowsDimensions()))),this.register((0,l.addDisposableDomListener)(document,"selectionchange",(()=>this._handleSelectionChange()))),this.register(this._coreBrowserService.onDprChange((()=>this._refreshRowsDimensions()))),this._refreshRows(),this.register((0,a.toDisposable)((()=>{this._accessibilityContainer.remove(),this._rowElements.length=0})))}_handleTab(e){for(let t=0;t<e;t++)this._handleChar(" ")}_handleChar(e){this._liveRegionLineCount<21&&(this._charsToConsume.length>0?this._charsToConsume.shift()!==e&&(this._charsToAnnounce+=e):this._charsToAnnounce+=e,"\n"===e&&(this._liveRegionLineCount++,21===this._liveRegionLineCount&&(this._liveRegion.textContent+=n.tooMuchOutput)))}_clearLiveRegion(){this._liveRegion.textContent="",this._liveRegionLineCount=0}_handleKey(e){this._clearLiveRegion(),/\p{Control}/u.test(e)||this._charsToConsume.push(e)}_refreshRows(e,t){this._liveRegionDebouncer.refresh(e,t,this._terminal.rows)}_renderRows(e,t){const i=this._terminal.buffer,s=i.lines.length.toString();for(let r=e;r<=t;r++){const e=i.lines.get(i.ydisp+r),t=[],n=e?.translateToString(!0,void 0,void 0,t)||"",o=(i.ydisp+r+1).toString(),a=this._rowElements[r];a&&(0===n.length?(a.innerText=" ",this._rowColumns.set(a,[0,1])):(a.textContent=n,this._rowColumns.set(a,t)),a.setAttribute("aria-posinset",o),a.setAttribute("aria-setsize",s))}this._announceCharacters()}_announceCharacters(){0!==this._charsToAnnounce.length&&(this._liveRegion.textContent+=this._charsToAnnounce,this._charsToAnnounce="")}_handleBoundaryFocus(e,t){const i=e.target,s=this._rowElements[0===t?1:this._rowElements.length-2];if(i.getAttribute("aria-posinset")===(0===t?"1":`${this._terminal.buffer.lines.length}`))return;if(e.relatedTarget!==s)return;let r,n;if(0===t?(r=i,n=this._rowElements.pop(),this._rowContainer.removeChild(n)):(r=this._rowElements.shiftLine truncated
//# sourceMappingURL=xterm.js.map
+45 -8
View File
@@ -1,6 +1,5 @@
:root { :root {
--host-bg: #11111b; --host-bg: #11111b;
--host-surface: #1a1b26;
} }
* { * {
@@ -16,11 +15,49 @@ html, body {
background: var(--host-bg); background: var(--host-bg);
} }
#terminal { /* terminal.js reads the --term-* properties for xterm's theme. FitAddon sizes
position: absolute; the grid from #chess-terminal-screen, so the box needs a definite height. */
top: 0; .chess-terminal {
left: 0; --term-bg: #1a1b26;
right: 0; --term-fg: #a9b1d6;
bottom: 0; --term-cursor: #a9b1d6;
overflow: hidden; --term-selection: rgba(169, 177, 214, 0.35);
display: grid;
height: 100%;
background: var(--term-bg);
}
/* The status line shares the screen's grid cell. */
.chess-terminal > * {
grid-area: 1 / 1;
min-width: 0;
min-height: 0;
}
.chess-terminal-status {
/* Above xterm's positioned layers, which would otherwise paint over it. */
position: relative;
z-index: 1;
place-self: center;
margin: 0;
padding: 0 1.5rem;
text-align: center;
color: var(--term-fg);
font-family: sans-serif;
pointer-events: none;
}
.chess-terminal-status.is-error {
color: #f7768e;
pointer-events: auto;
}
.chess-terminal-progress {
font-variant-numeric: tabular-nums;
}
.chess-terminal-progress:not(:empty)::before {
content: " ";
} }
+247 -96
View File
@@ -1,130 +1,281 @@
// Runs the WASM client in #chess-terminal: its data-wasm-url names the binary,
// #chess-terminal-screen holds xterm, #chess-terminal-status (-state and
// -progress spans) reports loading. xterm with its fit and WebGL addons and
// wasm_exec.js load first. lixen.com wraps this same file in its own page.
(() => {
'use strict';
const host = document.getElementById('chess-terminal');
if (!host) return;
const screenEl = document.getElementById('chess-terminal-screen');
const status = document.getElementById('chess-terminal-status');
const stateEl = document.getElementById('chess-terminal-state');
const progress = document.getElementById('chess-terminal-progress');
const wasmURL = host.dataset.wasmUrl;
const setState = (text, isError) => {
stateEl.textContent = text;
progress.textContent = '';
status.hidden = !text && !isError;
status.classList.toggle('is-error', !!isError);
};
// A page script that should have removed .no-js may have been blocked; its
// no-JS message would then cover a working terminal.
document.documentElement.classList.remove('no-js');
if (typeof Terminal === 'undefined' || typeof FitAddon === 'undefined') {
setState('Terminal library failed to load. Reload the page to retry.', true);
return;
}
if (typeof Go === 'undefined' || !globalThis.fs) {
setState('WebAssembly support files failed to load. Reload the page to retry.', true);
return;
}
// The theme's colours are the host's CSS custom properties.
const css = getComputedStyle(host);
const token = (name, fallback) => css.getPropertyValue(name).trim() || fallback;
const term = new Terminal({ const term = new Terminal({
cursorBlink: true, cursorBlink: true,
convertEol: true, convertEol: true,
fontFamily: 'Menlo, Monaco, "Courier New", monospace', scrollback: 1000,
fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace',
fontSize: 14, fontSize: 14,
allowProposedApi: true,
theme: { theme: {
background: '#1a1b26', background: token('--term-bg', '#1a1b26'),
foreground: '#a9b1d6', foreground: token('--term-fg', '#a9b1d6'),
cursor: '#a9b1d6', cursor: token('--term-cursor', '#a9b1d6'),
selection: 'rgba(169, 177, 214, 0.3)' // xterm 5 silently ignores the old `selection` key.
selectionBackground: token('--term-selection', 'rgba(169,177,214,0.35)')
} }
}); });
// Load addons
const fitAddon = new FitAddon.FitAddon(); const fitAddon = new FitAddon.FitAddon();
const webglAddon = new WebglAddon.WebglAddon();
const webLinksAddon = new WebLinksAddon.WebLinksAddon();
const unicode11Addon = new Unicode11Addon.Unicode11Addon();
term.loadAddon(fitAddon); term.loadAddon(fitAddon);
term.loadAddon(webLinksAddon);
term.loadAddon(unicode11Addon);
term.unicode.activeVersion = '11';
term.open(document.getElementById('terminal')); term.open(screenEl);
// WebGL addon must load after open() // WebGL must load after open(); the DOM renderer is the fallback.
try { try {
term.loadAddon(webglAddon); const webgl = new WebglAddon.WebglAddon();
webglAddon.onContextLoss(() => { webgl.onContextLoss(() => webgl.dispose());
webglAddon.dispose(); term.loadAddon(webgl);
});
} catch (e) { } catch (e) {
console.warn('WebGL addon failed, using canvas renderer:', e); console.warn('xterm: WebGL renderer unavailable, using the DOM renderer', e);
} }
fitAddon.fit(); // xterm captures Tab, so Escape, which the line editor ignores, is the
term.focus(); // keyboard way out of the terminal (WCAG 2.1.2).
term.attachCustomKeyEventHandler((e) => {
let inputBuffer = ''; if (e.type === 'keydown' && e.key === 'Escape') {
let inputResolver = null; term.blur();
return false;
term.onData(data => {
if (inputResolver) {
if (data === '\r') {
term.write('\r\n');
const result = inputBuffer;
inputBuffer = '';
const resolver = inputResolver;
inputResolver = null;
resolver(result);
} else if (data === '\x7f' || data === '\x08') {
if (inputBuffer.length > 0) {
inputBuffer = inputBuffer.slice(0, -1);
term.write('\b \b');
}
} else if (data === '\x03') {
term.write('^C\r\n');
inputBuffer = '';
if (inputResolver) {
inputResolver('');
inputResolver = null;
}
} else if (data >= ' ' && data <= '~') {
inputBuffer += data;
term.write(data);
}
} }
return true;
}); });
// fit() floors rows against the cell height it knew at call time, which a
// zoom step can leave stale: drop a row while .xterm-screen (rows x cell
// height) paints taller than the box.
const availHeight = () => {
const cs = getComputedStyle(screenEl);
return screenEl.clientHeight
- parseFloat(cs.paddingTop) - parseFloat(cs.paddingBottom);
};
const snapRows = () => {
const scr = term.element && term.element.querySelector('.xterm-screen');
if (!scr || !term.rows) return;
const cell = scr.getBoundingClientRect().height / term.rows;
if (!cell) return;
const max = Math.max(1, Math.floor(availHeight() / cell));
if (term.rows > max) term.resize(term.cols, max);
};
const fitNow = (passes) => {
fitAddon.fit();
snapRows();
if (passes > 1) requestAnimationFrame(() => fitNow(passes - 1));
};
let fitTimer = 0;
const scheduleFit = () => {
clearTimeout(fitTimer);
fitTimer = setTimeout(() => fitNow(2), 50);
};
// A resolution query matches one ratio only, so re-arm on every change.
let dprQuery = null;
const onDprChange = () => { watchDpr(); scheduleFit(); };
const watchDpr = () => {
if (dprQuery) dprQuery.removeEventListener('change', onDprChange);
dprQuery = window.matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`);
dprQuery.addEventListener('change', onDprChange);
};
fitNow(2);
new ResizeObserver(scheduleFit).observe(screenEl);
window.addEventListener('resize', scheduleFit);
watchDpr();
if (document.fonts && document.fonts.ready) document.fonts.ready.then(scheduleFit);
screenEl.addEventListener('click', () => term.focus());
// Go's js/wasm routes os.Stdout and os.Stderr through fs.write, runtime
// prints (panics) through fs.writeSync and os.Stdin through fs.read: fds
// 0-2 go to xterm, the rest to wasm_exec.js's own implementations.
const fs = globalThis.fs;
const nativeWrite = fs.write;
const nativeWriteSync = fs.writeSync;
const nativeRead = fs.read;
const encoder = new TextEncoder(); const encoder = new TextEncoder();
const decoder = new TextDecoder(); // One streaming decoder per fd: a UTF-8 sequence split across two writes
// must not lend its tail to the other stream.
const decoders = { 1: new TextDecoder('utf-8'), 2: new TextDecoder('utf-8') };
const toTerminal = (fd, bytes) => term.write(decoders[fd].decode(bytes, { stream: true }));
if (!globalThis.fs) { fs.writeSync = function (fd, buf) {
globalThis.fs = {};
}
const originalWrite = globalThis.fs.write;
const originalRead = globalThis.fs.read;
globalThis.fs.write = function(fd, buf, offset, length, position, callback) {
if (fd === 1 || fd === 2) { if (fd === 1 || fd === 2) {
const text = decoder.decode(buf.slice(offset, offset + length)); toTerminal(fd, buf);
term.write(text); return buf.length;
callback(null, length);
} else if (originalWrite) {
originalWrite.call(this, fd, buf, offset, length, position, callback);
} else {
callback(new Error('Invalid fd'));
} }
return nativeWriteSync.call(this, fd, buf);
}; };
globalThis.fs.read = function(fd, buf, offset, length, position, callback) { fs.write = function (fd, buf, offset, length, position, callback) {
if (fd === 0) { if (fd === 1 || fd === 2) {
const promise = new Promise(resolve => { toTerminal(fd, buf.subarray(offset, offset + length));
inputResolver = resolve; callback(null, length); // synchronous, exactly as wasm_exec.js does
return;
}
nativeWrite.call(this, fd, buf, offset, length, position, callback);
};
// Line editor. Input is taken only while Go blocks in read: keys buffered
// across a read would echo twice. Per character, so a pasted "e2e4\r"
// submits; a multi-line paste submits its first line and drops the rest,
// which Go's next read would echo over a screen the client has repainted.
let line = '';
let pendingRead = null;
let esc = 0; // 0 none, 1 saw ESC, 2 inside CSI/SS3
term.onData((data) => {
if (!pendingRead) return;
for (const ch of data) {
// Escape sequences (an arrow key) type nothing; CSI/SS3 end on 0x40-0x7E.
if (esc === 1) { esc = (ch === '[' || ch === 'O') ? 2 : 0; continue; }
if (esc === 2) { if (ch >= '@' && ch <= '~') esc = 0; continue; }
if (ch === '\x1b') { esc = 1; continue; }
if (ch === '\r') {
term.write('\r\n');
const resolve = pendingRead, value = line;
pendingRead = null; line = ''; esc = 0;
resolve(value);
return;
}
if (ch === '\x03') { // Ctrl-C
term.write('^C\r\n');
const resolve = pendingRead;
pendingRead = null; line = ''; esc = 0;
resolve('');
return;
}
if (ch === '\x7f' || ch === '\b') {
if (line.length > 0) { line = line.slice(0, -1); term.write('\b \b'); }
continue;
}
if (ch >= ' ' && ch <= '~') { line += ch; term.write(ch); }
}
}); });
promise.then(line => { // The bytes of a submitted line that did not fit the caller's buffer.
const input = encoder.encode(line + '\n'); let residual = null;
const n = Math.min(length, input.length);
buf.set(input.slice(0, n), offset); fs.read = function (fd, buf, offset, length, position, callback) {
if (fd !== 0) {
nativeRead.call(this, fd, buf, offset, length, position, callback);
return;
}
const deliver = (bytes) => {
const n = Math.min(length, bytes.length);
buf.set(bytes.subarray(0, n), offset);
residual = n < bytes.length ? bytes.subarray(n) : null;
callback(null, n); callback(null, n);
}); };
} else if (originalRead) { if (residual) {
originalRead.call(this, fd, buf, offset, length, position, callback); // Resolving inside the fs.read call would re-enter the Go runtime
} else { // through _resume() while it is still on the stack.
callback(new Error('Invalid fd')); const pending = residual;
residual = null;
queueMicrotask(() => deliver(pending));
return;
} }
new Promise((resolve) => { pendingRead = resolve; })
.then((value) => deliver(encoder.encode(value + '\n')));
}; };
const MB = 1048576;
// One unit on the pair: "2.1 / 10.3 MB".
const fmtBytes = (received, total) => total
? (received / MB).toFixed(1) + ' / ' + (total / MB).toFixed(1) + ' MB'
: (received / MB).toFixed(1) + ' MB';
(async () => {
const go = new Go(); const go = new Go();
let instance;
WebAssembly.instantiateStreaming(fetch('chess-client.wasm'), go.importObject) try {
.then(result => { const response = await fetch(wasmURL);
go.run(result.instance); if (!response.ok) throw new Error('HTTP ' + response.status);
})
.catch(err => {
term.writeln('\r\n\x1b[31mError loading WASM: ' + err + '\x1b[0m');
console.error('WASM load error:', err);
});
// Resize handling with debounce for performance let bytes;
let resizeTimeout; if (response.body) {
const resizeObserver = new ResizeObserver(() => { const reader = response.body.getReader();
clearTimeout(resizeTimeout); const chunks = [];
resizeTimeout = setTimeout(() => fitAddon.fit(), 16); let received = 0;
}); // The transferred length: compressed in transit, it is smaller
resizeObserver.observe(document.getElementById('terminal')); // than the decoded chunks, so it is dropped once they pass it.
let total = Number(response.headers.get('content-length')) || 0;
for (;;) {
const { done, value } = await reader.read();
if (done) break;
chunks.push(value);
received += value.length;
if (total && received > total) total = 0;
progress.textContent = fmtBytes(received, total);
}
bytes = new Uint8Array(received);
let offset = 0;
for (const chunk of chunks) { bytes.set(chunk, offset); offset += chunk.length; }
} else {
bytes = new Uint8Array(await response.arrayBuffer());
}
setState('Compiling the client…');
const result = await WebAssembly.instantiate(bytes, go.importObject);
instance = result.instance;
} catch (err) {
console.error('chess terminal: WASM load failed', err);
setState('Could not load the client (' + err.message + '). Reload to retry.', true);
return;
}
setState('');
// The page is the terminal, opened on purpose; Escape is the way out.
term.focus();
go.run(instance).then(
// Unreached while the client restarts on exit (exit_wasm.go).
() => setState('Session ended. Reload the page to start a new one.'),
(err) => {
console.error('chess terminal: client crashed', err);
setState('Client crashed: ' + err.message, true);
}
);
})();
})();