diff --git a/.woodpecker.yml b/.woodpecker.yml index e64cebe..7b97531 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -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/ diff --git a/assets/FiraCode-Bold.woff2 b/assets/FiraCode-Bold.woff2 new file mode 100644 index 0000000..349dc36 Binary files /dev/null and b/assets/FiraCode-Bold.woff2 differ diff --git a/assets/FiraCode-Regular.woff2 b/assets/FiraCode-Regular.woff2 new file mode 100644 index 0000000..f8b63fb Binary files /dev/null and b/assets/FiraCode-Regular.woff2 differ diff --git a/package.json b/package.json index f23e68c..3780e86 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a3fe4a3..e09309c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -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: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..220490e --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,3 @@ +packages: + - 'thecockpit' + - '.' diff --git a/src/components/head.html b/src/components/head.html index 4fb8184..fc4db02 100644 --- a/src/components/head.html +++ b/src/components/head.html @@ -8,12 +8,10 @@ The SANDWICH - - - + + diff --git a/src/firacode.css b/src/firacode.css new file mode 100644 index 0000000..9a41409 --- /dev/null +++ b/src/firacode.css @@ -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; +} + diff --git a/src/partials/page_four.html b/src/partials/page_four.html index 5a93094..cd45f10 100644 --- a/src/partials/page_four.html +++ b/src/partials/page_four.html @@ -30,4 +30,19 @@
- \ No newline at end of file +
+ + + + + + \ No newline at end of file diff --git a/src/partials/projects.html b/src/partials/projects.html index 5ac3084..930ac9f 100644 --- a/src/partials/projects.html +++ b/src/partials/projects.html @@ -228,4 +228,9 @@ - \ No newline at end of file + + + + + + \ No newline at end of file diff --git a/src/style.css b/src/style.css index ba91927..5a2ed44 100644 --- a/src/style.css +++ b/src/style.css @@ -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; } diff --git a/thecockpit/.gitignore b/thecockpit/.gitignore new file mode 100644 index 0000000..4e30131 --- /dev/null +++ b/thecockpit/.gitignore @@ -0,0 +1,6 @@ +/target +**/*.rs.bk +Cargo.lock +bin/ +pkg/ +wasm-pack.log diff --git a/thecockpit/Cargo.toml b/thecockpit/Cargo.toml new file mode 100644 index 0000000..b8a3e01 --- /dev/null +++ b/thecockpit/Cargo.toml @@ -0,0 +1,46 @@ +[package] +name = "thecockpit" +version = "0.1.0" +authors = ["Isaac Mills "] +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" diff --git a/thecockpit/README.md b/thecockpit/README.md new file mode 100644 index 0000000..6b68408 --- /dev/null +++ b/thecockpit/README.md @@ -0,0 +1,84 @@ +
+ +

wasm-pack-template

+ + A template for kick starting a Rust and WebAssembly project using wasm-pack. + +

+ Build Status +

+ +

+ Tutorial + | + Chat +

+ + Built with 🦀🕸 by The Rust and WebAssembly Working Group +
+ +## 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. diff --git a/thecockpit/package.json b/thecockpit/package.json new file mode 100644 index 0000000..47a07be --- /dev/null +++ b/thecockpit/package.json @@ -0,0 +1,8 @@ +{ + "scripts": { + "build": "wasm-pack build --target web --release" + }, + "devDependencies": { + "wasm-pack": "^0.13.1" + } +} diff --git a/thecockpit/pnpm-lock.yaml b/thecockpit/pnpm-lock.yaml new file mode 100644 index 0000000..55efd94 --- /dev/null +++ b/thecockpit/pnpm-lock.yaml @@ -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: {} diff --git a/thecockpit/src/lib.rs b/thecockpit/src/lib.rs new file mode 100644 index 0000000..01bb747 --- /dev/null +++ b/thecockpit/src/lib.rs @@ -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, +} + +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()); + } +} diff --git a/thecockpit/src/main.rs b/thecockpit/src/main.rs new file mode 100644 index 0000000..e2123cb --- /dev/null +++ b/thecockpit/src/main.rs @@ -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(); +} diff --git a/thecockpit/src/native/mod.rs b/thecockpit/src/native/mod.rs new file mode 100644 index 0000000..048085b --- /dev/null +++ b/thecockpit/src/native/mod.rs @@ -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), + _ => {} + } + } +} diff --git a/thecockpit/src/web/mod.rs b/thecockpit/src/web/mod.rs new file mode 100644 index 0000000..534a1e2 --- /dev/null +++ b/thecockpit/src/web/mod.rs @@ -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), + _ => {} + } + } +} diff --git a/thecockpit/src/web/utils.rs b/thecockpit/src/web/utils.rs new file mode 100644 index 0000000..b1d7929 --- /dev/null +++ b/thecockpit/src/web/utils.rs @@ -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(); +}