Try to build WASM on page 4
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed

This commit is contained in:
Isaac Mills 2025-07-15 14:47:46 -06:00
parent 09623f73aa
commit 953ea4e6c4
Signed by: fnmain
GPG key ID: B67D7410F33A0F61
21 changed files with 771 additions and 8 deletions

View file

@ -7,7 +7,7 @@ steps:
commands:
- corepack enable
- pnpm install
- pnpm run build --no-cache
- pnpm run build
- rm -rf /var/woodpecker/thesandwich/*
- mkdir -p /var/woodpecker/thesandwich/
- mv dist/* /var/woodpecker/thesandwich/

BIN
assets/FiraCode-Bold.woff2 Normal file

Binary file not shown.

Binary file not shown.

View file

@ -9,7 +9,7 @@
],
"scripts": {
"start": "parcel",
"build": "parcel build"
"build": "pnpm run -r build; parcel build"
},
"devDependencies": {
"@parcel/compressor-brotli": "^2.15.4",
@ -23,7 +23,8 @@
"posthtml-component": "github:StratusFearMe21/posthtml-components#reorder_processing",
"posthtml-include": "^2.0.1",
"posthtml-markdownit": "^3.1.2",
"sharp": "^0.33.5"
"sharp": "^0.33.5",
"thecockpit": "link:./thecockpit/pkg"
},
"dependencies": {
"audiomotion-analyzer": "^4.5.1",

197
pnpm-lock.yaml generated
View file

@ -51,6 +51,15 @@ importers:
sharp:
specifier: ^0.33.5
version: 0.33.5
thecockpit:
specifier: link:./thecockpit/pkg
version: link:thecockpit/pkg
thecockpit:
devDependencies:
wasm-pack:
specifier: ^0.13.1
version: 0.13.1
packages:
@ -704,12 +713,25 @@ packages:
audiomotion-analyzer@4.5.1:
resolution: {integrity: sha512-vEO5HgivsZa9ZhQDItSMjXD5+qsRu6rAEKzAmrg7HbOFeM4tPVrE/wxiRREWxzbGpuH9NZT4Ze+v95G1w/rRAA==}
axios@0.26.1:
resolution: {integrity: sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==}
balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
base-x@3.0.11:
resolution: {integrity: sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA==}
binary-install@1.1.0:
resolution: {integrity: sha512-rkwNGW+3aQVSZoD0/o3mfPN6Yxh3Id0R/xzTVBVVpGNlVz8EGwusksxRlbk/A5iKTZt9zkMn3qIqmAt3vpfbzg==}
engines: {node: '>=10'}
boolbase@1.0.0:
resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==}
brace-expansion@1.1.12:
resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==}
braces@3.0.3:
resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
engines: {node: '>=8'}
@ -729,6 +751,10 @@ packages:
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
engines: {node: '>=10'}
chownr@2.0.0:
resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==}
engines: {node: '>=10'}
chrome-trace-event@1.0.4:
resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==}
engines: {node: '>=6.0'}
@ -762,6 +788,9 @@ packages:
resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==}
engines: {node: '>=18'}
concat-map@0.0.1:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
css-declaration-sorter@7.2.0:
resolution: {integrity: sha512-h70rUM+3PNFuaBDTLe8wF/cdWu+dOZmb7pJt8Z2sedYbAcQVQV/tEchueg3GWxwqS0cxtbxmaHEdkNACqcvsow==}
engines: {node: ^14 || ^16 || >=18}
@ -875,10 +904,30 @@ packages:
resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
engines: {node: '>=8'}
follow-redirects@1.15.9:
resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==}
engines: {node: '>=4.0'}
peerDependencies:
debug: '*'
peerDependenciesMeta:
debug:
optional: true
fs-minipass@2.1.0:
resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==}
engines: {node: '>= 8'}
fs.realpath@1.0.0:
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
get-port@4.2.0:
resolution: {integrity: sha512-/b3jarXkH8KJoOMQc3uVGHASwGLPq3gSFJ7tgJm2diza+bydJPTGOibin2steecKeOylE8oY2JERlVWkAJO6yw==}
engines: {node: '>=6'}
glob@7.2.3:
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
deprecated: Glob versions prior to v9 are no longer supported
globals@13.24.0:
resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==}
engines: {node: '>=8'}
@ -896,6 +945,13 @@ packages:
htmx.org@2.0.6:
resolution: {integrity: sha512-7ythjYneGSk3yCHgtCnQeaoF+D+o7U2LF37WU3O0JYv3gTZSicdEFiI/Ai/NJyC5ZpYJWMpUb11OC5Lr6AfAqA==}
inflight@1.0.6:
resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
inherits@2.0.4:
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
inline-style-parser@0.2.4:
resolution: {integrity: sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==}
@ -1030,6 +1086,26 @@ packages:
resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==}
engines: {node: '>=4'}
minimatch@3.1.2:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
minipass@3.3.6:
resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==}
engines: {node: '>=8'}
minipass@5.0.0:
resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==}
engines: {node: '>=8'}
minizlib@2.1.2:
resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==}
engines: {node: '>= 8'}
mkdirp@1.0.4:
resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==}
engines: {node: '>=10'}
hasBin: true
msgpackr-extract@3.0.3:
resolution: {integrity: sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==}
hasBin: true
@ -1065,6 +1141,9 @@ packages:
nullthrows@1.1.1:
resolution: {integrity: sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==}
once@1.4.0:
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
ordered-binary@1.6.0:
resolution: {integrity: sha512-IQh2aMfMIDbPjI/8a3Edr+PiOpcsB7yo8NdW7aHWVaoR/pcDldunMvnnwbk/auPGqmKeAdxtZl7MHX/QmPwhvQ==}
@ -1073,6 +1152,10 @@ packages:
engines: {node: '>= 16.0.0'}
hasBin: true
path-is-absolute@1.0.1:
resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
engines: {node: '>=0.10.0'}
picocolors@1.1.1:
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
@ -1310,6 +1393,11 @@ packages:
regenerator-runtime@0.14.1:
resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==}
rimraf@3.0.2:
resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
deprecated: Rimraf versions prior to v4 are no longer supported
hasBin: true
safe-buffer@5.2.1:
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
@ -1350,6 +1438,10 @@ packages:
engines: {node: '>=16'}
hasBin: true
tar@6.2.1:
resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==}
engines: {node: '>=10'}
term-size@2.2.1:
resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==}
engines: {node: '>=8'}
@ -1381,9 +1473,19 @@ packages:
resolution: {integrity: sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw==}
engines: {node: '>= 4'}
wasm-pack@0.13.1:
resolution: {integrity: sha512-P9exD4YkjpDbw68xUhF3MDm/CC/3eTmmthyG5bHJ56kalxOTewOunxTke4SyF8MTXV6jUtNjXggPgrGmMtczGg==}
hasBin: true
weak-lru-cache@1.2.2:
resolution: {integrity: sha512-DEAoo25RfSYMuTGc9vPJzZcZullwIqRDSI9LOy+fkCJPi6hykCnfKaXTuPBDuXAUcqHXyOgFtHNp/kB2FjYHbw==}
wrappy@1.0.2:
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
yallist@4.0.0:
resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
snapshots:
'@emnapi/runtime@1.4.4':
@ -2251,12 +2353,33 @@ snapshots:
audiomotion-analyzer@4.5.1: {}
axios@0.26.1:
dependencies:
follow-redirects: 1.15.9
transitivePeerDependencies:
- debug
balanced-match@1.0.2: {}
base-x@3.0.11:
dependencies:
safe-buffer: 5.2.1
binary-install@1.1.0:
dependencies:
axios: 0.26.1
rimraf: 3.0.2
tar: 6.2.1
transitivePeerDependencies:
- debug
boolbase@1.0.0: {}
brace-expansion@1.1.12:
dependencies:
balanced-match: 1.0.2
concat-map: 0.0.1
braces@3.0.3:
dependencies:
fill-range: 7.1.1
@ -2282,6 +2405,8 @@ snapshots:
ansi-styles: 4.3.0
supports-color: 7.2.0
chownr@2.0.0: {}
chrome-trace-event@1.0.4: {}
clone@2.1.2: {}
@ -2308,6 +2433,8 @@ snapshots:
commander@12.1.0: {}
concat-map@0.0.1: {}
css-declaration-sorter@7.2.0(postcss@8.5.6):
dependencies:
postcss: 8.5.6
@ -2442,8 +2569,25 @@ snapshots:
dependencies:
to-regex-range: 5.0.1
follow-redirects@1.15.9: {}
fs-minipass@2.1.0:
dependencies:
minipass: 3.3.6
fs.realpath@1.0.0: {}
get-port@4.2.0: {}
glob@7.2.3:
dependencies:
fs.realpath: 1.0.0
inflight: 1.0.6
inherits: 2.0.4
minimatch: 3.1.2
once: 1.4.0
path-is-absolute: 1.0.1
globals@13.24.0:
dependencies:
type-fest: 0.20.2
@ -2466,6 +2610,13 @@ snapshots:
htmx.org@2.0.6: {}
inflight@1.0.6:
dependencies:
once: 1.4.0
wrappy: 1.0.2
inherits@2.0.4: {}
inline-style-parser@0.2.4: {}
is-arrayish@0.3.2: {}
@ -2578,6 +2729,23 @@ snapshots:
min-indent@1.0.1: {}
minimatch@3.1.2:
dependencies:
brace-expansion: 1.1.12
minipass@3.3.6:
dependencies:
yallist: 4.0.0
minipass@5.0.0: {}
minizlib@2.1.2:
dependencies:
minipass: 3.3.6
yallist: 4.0.0
mkdirp@1.0.4: {}
msgpackr-extract@3.0.3:
dependencies:
node-gyp-build-optional-packages: 5.2.2
@ -2617,6 +2785,10 @@ snapshots:
nullthrows@1.1.1: {}
once@1.4.0:
dependencies:
wrappy: 1.0.2
ordered-binary@1.6.0: {}
parcel@2.15.4(@swc/helpers@0.5.17):
@ -2640,6 +2812,8 @@ snapshots:
- '@swc/helpers'
- napi-wasm
path-is-absolute@1.0.1: {}
picocolors@1.1.1: {}
picomatch@2.3.1: {}
@ -2871,6 +3045,10 @@ snapshots:
regenerator-runtime@0.14.1: {}
rimraf@3.0.2:
dependencies:
glob: 7.2.3
safe-buffer@5.2.1: {}
sax@1.4.1: {}
@ -2933,6 +3111,15 @@ snapshots:
picocolors: 1.1.1
sax: 1.4.1
tar@6.2.1:
dependencies:
chownr: 2.0.0
fs-minipass: 2.1.0
minipass: 5.0.0
minizlib: 2.1.2
mkdirp: 1.0.4
yallist: 4.0.0
term-size@2.2.1: {}
to-regex-range@5.0.1:
@ -2955,4 +3142,14 @@ snapshots:
utility-types@3.11.0: {}
wasm-pack@0.13.1:
dependencies:
binary-install: 1.1.0
transitivePeerDependencies:
- debug
weak-lru-cache@1.2.2: {}
wrappy@1.0.2: {}
yallist@4.0.0: {}

3
pnpm-workspace.yaml Normal file
View file

@ -0,0 +1,3 @@
packages:
- 'thecockpit'
- '.'

View file

@ -8,12 +8,10 @@
<title>The SANDWICH</title>
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="apex.css">
<link rel="preload" href="/assets/ApexMk2-Regular.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/assets/ApexMk2-LightCondensed.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/assets/ApexMk2-BoldExtended.woff2" as="font" type="font/woff2" crossorigin>
<link rel="icon" href="/assets/favicon.ico" sizes="16x16 32x32">
<link rel="icon" href="/assets/favicon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/assets/apple-touch-icon.png">
<stack name="head"></stack>
<script type="module" src="index.js"></script>
<meta name="htmx-config" content='{"responseHandling": [{"code":"204", "swap": false},{"code":"...", "swap": true}]}'>
<style>
@ -76,6 +74,15 @@
}
}
</style>
<script type="module">
import init, * as bindings from '/thecockpit/pkg/thecockpit.js';
async function run() {
const wasm = await init({module_or_path: new URL('/thecockpit/pkg/thecockpit_bg.wasm', import.meta.url)});
bindings.cockpit('cockpit-canvas');
}
bindings.run = run;
window.wasmBindings = bindings;
</script>
</head>

18
src/firacode.css Normal file
View file

@ -0,0 +1,18 @@
@font-face {
font-family: 'Fira Code';
src: url('FiraCode-Regular.woff2') format('woff2'),
url('FiraCode-Regular.woff') format('woff');
font-weight: normal;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Fira Code';
src: url('FiraCode-Bold.woff2') format('woff2'),
url('FiraCode-Bold.woff') format('woff');
font-weight: bold;
font-style: normal;
font-display: swap;
}

View file

@ -30,4 +30,19 @@
<div id="page-idea-result"></div>
</fill:description>
</x-project>
</x-tab.content>
<div id="cockpit-canvas"></div>
</x-tab.content>
<script>
var x = setInterval(runCockpit, 500);
function runCockpit() {
if (window.wasmBindings != undefined) {
window.wasmBindings.run();
clearInterval(x)
}
}
runCockpit();
</script>
<push name="head">
<link rel="preload" href="/assets/FiraCode-Bold.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/assets/FiraCode-Regular.woff2" as="font" type="font/woff2" crossorigin>
</push>

View file

@ -228,4 +228,9 @@
</li>
</ol>
</fill:footer>
</x-tab.content>
</x-tab.content>
<push name="head">
<link rel="preload" href="/assets/ApexMk2-Regular.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/assets/ApexMk2-LightCondensed.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/assets/ApexMk2-BoldExtended.woff2" as="font" type="font/woff2" crossorigin>
</push>

View file

@ -254,6 +254,25 @@ blockquote {
margin: 15px 0;
}
#cockpit-canvas {
margin: 0;
width: 100%;
height: 70vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
align-content: center;
background-color: #121212;
pre {
font-family: "Fira Code", monospace;
font-size: 16px;
margin: 0px;
}
}
body {
margin: 0;
}

6
thecockpit/.gitignore vendored Normal file
View file

@ -0,0 +1,6 @@
/target
**/*.rs.bk
Cargo.lock
bin/
pkg/
wasm-pack.log

46
thecockpit/Cargo.toml Normal file
View file

@ -0,0 +1,46 @@
[package]
name = "thecockpit"
version = "0.1.0"
authors = ["Isaac Mills <rooster0055@protonmail.com>"]
edition = "2018"
[profile.dev.package."*"]
opt-level = 3
[lib]
crate-type = ["cdylib", "rlib"]
[features]
default = ["console_error_panic_hook"]
crossterm = ["ratatui/crossterm"]
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
ratatui = { version = "0.29.0", default-features = false }
[target.'cfg(target_arch = "wasm32")'.dependencies]
ratatui = { version = "0.29.0", default-features = false }
ratzilla = "0.1.0"
wasm-bindgen = "0.2.84"
# The `console_error_panic_hook` crate provides better debugging of panics by
# logging them with `console.error`. This is great for development, but requires
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
# code size when deploying.
console_error_panic_hook = { version = "0.1.7", optional = true }
[target.'cfg(target_arch = "wasm32")'.dev-dependencies]
wasm-bindgen-test = "0.3.34"
[package.metadata.wasm-pack.profile.release]
wasm-opt = ['--enable-bulk-memory-opt', '--enable-mutable-globals', '--enable-nontrapping-float-to-int']
# wasm-opt = false
[profile.dev]
panic = "abort"
[profile.release]
opt-level = 2
lto = true
codegen-units = 1
strip = true
panic = "abort"

84
thecockpit/README.md Normal file
View file

@ -0,0 +1,84 @@
<div align="center">
<h1><code>wasm-pack-template</code></h1>
<strong>A template for kick starting a Rust and WebAssembly project using <a href="https://github.com/rustwasm/wasm-pack">wasm-pack</a>.</strong>
<p>
<a href="https://travis-ci.org/rustwasm/wasm-pack-template"><img src="https://img.shields.io/travis/rustwasm/wasm-pack-template.svg?style=flat-square" alt="Build Status" /></a>
</p>
<h3>
<a href="https://rustwasm.github.io/docs/wasm-pack/tutorials/npm-browser-packages/index.html">Tutorial</a>
<span> | </span>
<a href="https://discordapp.com/channels/442252698964721669/443151097398296587">Chat</a>
</h3>
<sub>Built with 🦀🕸 by <a href="https://rustwasm.github.io/">The Rust and WebAssembly Working Group</a></sub>
</div>
## About
[**📚 Read this template tutorial! 📚**][template-docs]
This template is designed for compiling Rust libraries into WebAssembly and
publishing the resulting package to NPM.
Be sure to check out [other `wasm-pack` tutorials online][tutorials] for other
templates and usages of `wasm-pack`.
[tutorials]: https://rustwasm.github.io/docs/wasm-pack/tutorials/index.html
[template-docs]: https://rustwasm.github.io/docs/wasm-pack/tutorials/npm-browser-packages/index.html
## 🚴 Usage
### 🐑 Use `cargo generate` to Clone this Template
[Learn more about `cargo generate` here.](https://github.com/ashleygwilliams/cargo-generate)
```
cargo generate --git https://github.com/rustwasm/wasm-pack-template.git --name my-project
cd my-project
```
### 🛠️ Build with `wasm-pack build`
```
wasm-pack build
```
### 🔬 Test in Headless Browsers with `wasm-pack test`
```
wasm-pack test --headless --firefox
```
### 🎁 Publish to NPM with `wasm-pack publish`
```
wasm-pack publish
```
## 🔋 Batteries Included
* [`wasm-bindgen`](https://github.com/rustwasm/wasm-bindgen) for communicating
between WebAssembly and JavaScript.
* [`console_error_panic_hook`](https://github.com/rustwasm/console_error_panic_hook)
for logging panic messages to the developer console.
* `LICENSE-APACHE` and `LICENSE-MIT`: most Rust projects are licensed this way, so these are included for you
## License
Licensed under either of
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option.
### Contribution
Unless you explicitly state otherwise, any contribution intentionally
submitted for inclusion in the work by you, as defined in the Apache-2.0
license, shall be dual licensed as above, without any additional terms or
conditions.

8
thecockpit/package.json Normal file
View file

@ -0,0 +1,8 @@
{
"scripts": {
"build": "wasm-pack build --target web --release"
},
"devDependencies": {
"wasm-pack": "^0.13.1"
}
}

205
thecockpit/pnpm-lock.yaml generated Normal file
View file

@ -0,0 +1,205 @@
lockfileVersion: '9.0'
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
importers:
.:
devDependencies:
wasm-pack:
specifier: ^0.13.1
version: 0.13.1
packages:
axios@0.26.1:
resolution: {integrity: sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==}
balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
binary-install@1.1.0:
resolution: {integrity: sha512-rkwNGW+3aQVSZoD0/o3mfPN6Yxh3Id0R/xzTVBVVpGNlVz8EGwusksxRlbk/A5iKTZt9zkMn3qIqmAt3vpfbzg==}
engines: {node: '>=10'}
brace-expansion@1.1.12:
resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==}
chownr@2.0.0:
resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==}
engines: {node: '>=10'}
concat-map@0.0.1:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
follow-redirects@1.15.9:
resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==}
engines: {node: '>=4.0'}
peerDependencies:
debug: '*'
peerDependenciesMeta:
debug:
optional: true
fs-minipass@2.1.0:
resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==}
engines: {node: '>= 8'}
fs.realpath@1.0.0:
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
glob@7.2.3:
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
deprecated: Glob versions prior to v9 are no longer supported
inflight@1.0.6:
resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
inherits@2.0.4:
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
minimatch@3.1.2:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
minipass@3.3.6:
resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==}
engines: {node: '>=8'}
minipass@5.0.0:
resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==}
engines: {node: '>=8'}
minizlib@2.1.2:
resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==}
engines: {node: '>= 8'}
mkdirp@1.0.4:
resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==}
engines: {node: '>=10'}
hasBin: true
once@1.4.0:
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
path-is-absolute@1.0.1:
resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
engines: {node: '>=0.10.0'}
rimraf@3.0.2:
resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
deprecated: Rimraf versions prior to v4 are no longer supported
hasBin: true
tar@6.2.1:
resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==}
engines: {node: '>=10'}
wasm-pack@0.13.1:
resolution: {integrity: sha512-P9exD4YkjpDbw68xUhF3MDm/CC/3eTmmthyG5bHJ56kalxOTewOunxTke4SyF8MTXV6jUtNjXggPgrGmMtczGg==}
hasBin: true
wrappy@1.0.2:
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
yallist@4.0.0:
resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
snapshots:
axios@0.26.1:
dependencies:
follow-redirects: 1.15.9
transitivePeerDependencies:
- debug
balanced-match@1.0.2: {}
binary-install@1.1.0:
dependencies:
axios: 0.26.1
rimraf: 3.0.2
tar: 6.2.1
transitivePeerDependencies:
- debug
brace-expansion@1.1.12:
dependencies:
balanced-match: 1.0.2
concat-map: 0.0.1
chownr@2.0.0: {}
concat-map@0.0.1: {}
follow-redirects@1.15.9: {}
fs-minipass@2.1.0:
dependencies:
minipass: 3.3.6
fs.realpath@1.0.0: {}
glob@7.2.3:
dependencies:
fs.realpath: 1.0.0
inflight: 1.0.6
inherits: 2.0.4
minimatch: 3.1.2
once: 1.4.0
path-is-absolute: 1.0.1
inflight@1.0.6:
dependencies:
once: 1.4.0
wrappy: 1.0.2
inherits@2.0.4: {}
minimatch@3.1.2:
dependencies:
brace-expansion: 1.1.12
minipass@3.3.6:
dependencies:
yallist: 4.0.0
minipass@5.0.0: {}
minizlib@2.1.2:
dependencies:
minipass: 3.3.6
yallist: 4.0.0
mkdirp@1.0.4: {}
once@1.4.0:
dependencies:
wrappy: 1.0.2
path-is-absolute@1.0.1: {}
rimraf@3.0.2:
dependencies:
glob: 7.2.3
tar@6.2.1:
dependencies:
chownr: 2.0.0
fs-minipass: 2.1.0
minipass: 5.0.0
minizlib: 2.1.2
mkdirp: 1.0.4
yallist: 4.0.0
wasm-pack@0.13.1:
dependencies:
binary-install: 1.1.0
transitivePeerDependencies:
- debug
wrappy@1.0.2: {}
yallist@4.0.0: {}

42
thecockpit/src/lib.rs Normal file
View file

@ -0,0 +1,42 @@
#[cfg(not(target_arch = "wasm32"))]
pub mod native;
#[cfg(target_arch = "wasm32")]
pub mod web;
use std::cell::RefCell;
use ratatui::{
layout::Alignment,
style::{Color, Stylize},
widgets::{Block, BorderType, Paragraph},
Frame,
};
#[derive(Default)]
pub struct App {
counter: RefCell<u8>,
}
impl App {
pub fn render(&self, frame: &mut Frame) {
let counter = self.counter.borrow();
let block = Block::bordered()
.title("thecockpit")
.title_alignment(Alignment::Center)
.border_type(BorderType::Rounded);
let text = format!(
"This is a Ratzilla template.\n\
Press left and right to increment and decrement the counter respectively.\n\
Counter: {counter}",
);
let paragraph = Paragraph::new(text)
.block(block)
.fg(Color::White)
.bg(Color::Black)
.centered();
frame.render_widget(paragraph, frame.area());
}
}

23
thecockpit/src/main.rs Normal file
View file

@ -0,0 +1,23 @@
use ratatui::crossterm::event::{self, KeyCode, KeyEvent};
use thecockpit::App;
fn main() {
let mut terminal = ratatui::init();
let app = App::default();
loop {
terminal
.draw(|frame| app.render(frame))
.expect("failed to draw frame");
match event::read().expect("failed to read event") {
event::Event::Key(key) => match key {
KeyEvent {
code: KeyCode::Char('q'),
..
} => break,
key => app.handle_events(key),
},
_ => {}
}
}
ratatui::restore();
}

View file

@ -0,0 +1,14 @@
use ratatui::crossterm::event::{KeyCode, KeyEvent};
use crate::App;
impl App {
pub fn handle_events(&self, key_event: KeyEvent) {
let mut counter = self.counter.borrow_mut();
match key_event.code {
KeyCode::Left => *counter = counter.saturating_sub(1),
KeyCode::Right => *counter = counter.saturating_add(1),
_ => {}
}
}
}

60
thecockpit/src/web/mod.rs Normal file
View file

@ -0,0 +1,60 @@
mod utils;
use std::{cell::RefCell, io, rc::Rc};
use ratatui::{
layout::Alignment,
style::{Color, Stylize},
widgets::{Block, BorderType, Paragraph},
Frame, Terminal,
};
use ratzilla::{
backend::canvas::{CanvasBackend, CanvasBackendOptions},
event::{KeyCode, KeyEvent},
WebRenderer,
};
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_namespace = console)]
fn log(s: &str);
}
#[wasm_bindgen]
pub fn cockpit(id: &str) {
utils::set_panic_hook();
start_cockpit(id).unwrap();
}
fn start_cockpit(id: &str) -> io::Result<()> {
let backend =
CanvasBackend::new_with_options(CanvasBackendOptions::new().grid_id("cockpit-canvas"))?;
let terminal = Terminal::new(backend)?;
let state = Rc::new(crate::App::default());
let event_state = Rc::clone(&state);
terminal.on_key_event(move |key_event| {
event_state.handle_events(key_event);
});
let render_state = Rc::clone(&state);
terminal.draw_web(move |frame| {
render_state.render(frame);
});
Ok(())
}
impl crate::App {
fn handle_events(&self, key_event: KeyEvent) {
// log(&format!("{:?}", key_event));
let mut counter = self.counter.borrow_mut();
match key_event.code {
KeyCode::Left => *counter = counter.saturating_sub(1),
KeyCode::Right => *counter = counter.saturating_add(1),
_ => {}
}
}
}

View file

@ -0,0 +1,10 @@
pub fn set_panic_hook() {
// When the `console_error_panic_hook` feature is enabled, we can call the
// `set_panic_hook` function at least once during initialization, and then
// we will get better error messages if our code ever panics.
//
// For more details see
// https://github.com/rustwasm/console_error_panic_hook#readme
#[cfg(feature = "console_error_panic_hook")]
console_error_panic_hook::set_once();
}