From e6f20af28d4a455f66b4d051cb21f4160dd758d0 Mon Sep 17 00:00:00 2001 From: Daniel Ledda Date: Wed, 30 Oct 2024 20:42:01 +0100 Subject: [PATCH] first commit --- .gitignore | 2 + app/App.tsx | 19 +++ app/test.tsx | 1 + deno.json | 23 ++++ deno.lock | 331 ++++++++++++++++++++++++++++++++++++++++++++++ deps.ts | 5 + main.ts | 42 ++++++ public/app.js | 4 + public/icon.webp | Bin 0 -> 23822 bytes public/image.jpeg | Bin 0 -> 9926 bytes public/index.html | 27 ++++ public/styles.css | 22 +++ transpileTs.ts | 80 +++++++++++ 13 files changed, 556 insertions(+) create mode 100644 .gitignore create mode 100644 app/App.tsx create mode 100644 app/test.tsx create mode 100644 deno.json create mode 100644 deno.lock create mode 100644 deps.ts create mode 100644 main.ts create mode 100644 public/app.js create mode 100644 public/icon.webp create mode 100644 public/image.jpeg create mode 100644 public/index.html create mode 100644 public/styles.css create mode 100644 transpileTs.ts diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a56a7ef --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules + diff --git a/app/App.tsx b/app/App.tsx new file mode 100644 index 0000000..ca3ca22 --- /dev/null +++ b/app/App.tsx @@ -0,0 +1,19 @@ +import { defineComponent, computed, ref } from "vue"; +import Test from '@/test.tsx'; + +export default defineComponent({ + name: "app-root", + setup() { + const count = ref(0); + const countDouble = computed(() => count.value * 2); + count.value++; + return () => ( +
+ +
Count: {count.value}
+
Count Double: {countDouble.value}
+ +
+ ); + }, +}); diff --git a/app/test.tsx b/app/test.tsx new file mode 100644 index 0000000..f8d8729 --- /dev/null +++ b/app/test.tsx @@ -0,0 +1 @@ +export default () =>
Test
; diff --git a/deno.json b/deno.json new file mode 100644 index 0000000..cd54a7a --- /dev/null +++ b/deno.json @@ -0,0 +1,23 @@ +{ + "tasks": { + "start": "deno --allow-read --allow-net --allow-env --allow-write --allow-run main.ts", + "watch": "deno --watch --allow-read --allow-net --allow-env --allow-write --allow-run main.ts" + }, + "fmt": { + "lineWidth": 120, + "indentWidth": 4 + }, + "imports": { + "@stock3/koala": "npm:@stock3/koala@^15.3.8-esm.0", + "vue": "npm:vue@^3.5.12", + "vue/jsx-runtime": "npm:vue/jsx-runtime", + "@/": "./app/" + }, + "nodeModulesDir": "auto", + "compilerOptions": { + "jsx": "react-jsx", + "jsxFactory": "h", + "jsxFragmentFactory": "Fragment", + "jsxImportSource": "vue" + } +} diff --git a/deno.lock b/deno.lock new file mode 100644 index 0000000..c671d10 --- /dev/null +++ b/deno.lock @@ -0,0 +1,331 @@ +{ + "version": "4", + "specifiers": { + "jsr:@deno/cache-dir@0.13.2": "0.13.2", + "jsr:@deno/emit@*": "0.46.0", + "jsr:@deno/graph@~0.73.1": "0.73.1", + "jsr:@luca/esbuild-deno-loader@0.11": "0.11.0", + "jsr:@std/assert@0.223": "0.223.0", + "jsr:@std/bytes@0.223": "0.223.0", + "jsr:@std/bytes@^1.0.2": "1.0.2", + "jsr:@std/cli@^1.0.6": "1.0.6", + "jsr:@std/encoding@^1.0.5": "1.0.5", + "jsr:@std/fmt@0.223": "0.223.0", + "jsr:@std/fmt@^1.0.3": "1.0.3", + "jsr:@std/fs@*": "1.0.5", + "jsr:@std/fs@0.223": "0.223.0", + "jsr:@std/http@*": "1.0.9", + "jsr:@std/io@0.223": "0.223.0", + "jsr:@std/media-types@*": "1.0.3", + "jsr:@std/media-types@^1.0.3": "1.0.3", + "jsr:@std/net@^1.0.4": "1.0.4", + "jsr:@std/path@0.223": "0.223.0", + "jsr:@std/path@^1.0.6": "1.0.7", + "jsr:@std/path@^1.0.7": "1.0.7", + "jsr:@std/streams@^1.0.7": "1.0.7", + "npm:@stock3/koala@^15.3.8-esm.0": "15.3.8-esm.0_@stock3+auth-js@4.2.3_bg-auth-legacy@2.5.0_bg-status-js@2.4.3_flora-client-js@0.5.3_m-gate@2.12.8_vue@3.5.12_vue-router@4.4.5__vue@3.5.12", + "npm:@types/node@*": "22.5.4", + "npm:vue@*": "3.5.12", + "npm:vue@3.5.12": "3.5.12", + "npm:vue@^3.5.12": "3.5.12" + }, + "jsr": { + "@deno/cache-dir@0.13.2": { + "integrity": "c22419dfe27ab85f345bee487aaaadba498b005cce3644e9d2528db035c5454d", + "dependencies": [ + "jsr:@deno/graph", + "jsr:@std/fmt@0.223", + "jsr:@std/fs@0.223", + "jsr:@std/io", + "jsr:@std/path@0.223" + ] + }, + "@deno/emit@0.46.0": { + "integrity": "e276be2c77bac1b93caf775762e2a49a54cb00da2d48ca2b01ed8d7cba9d082c", + "dependencies": [ + "jsr:@deno/cache-dir", + "jsr:@std/path@0.223" + ] + }, + "@deno/graph@0.73.1": { + "integrity": "cd69639d2709d479037d5ce191a422eabe8d71bb68b0098344f6b07411c84d41" + }, + "@luca/esbuild-deno-loader@0.11.0": { + "integrity": "c05a989aa7c4ee6992a27be5f15cfc5be12834cab7ff84cabb47313737c51a2c", + "dependencies": [ + "jsr:@std/bytes@^1.0.2", + "jsr:@std/encoding", + "jsr:@std/path@^1.0.6" + ] + }, + "@std/assert@0.223.0": { + "integrity": "eb8d6d879d76e1cc431205bd346ed4d88dc051c6366365b1af47034b0670be24" + }, + "@std/bytes@0.223.0": { + "integrity": "84b75052cd8680942c397c2631318772b295019098f40aac5c36cead4cba51a8" + }, + "@std/bytes@1.0.2": { + "integrity": "fbdee322bbd8c599a6af186a1603b3355e59a5fb1baa139f8f4c3c9a1b3e3d57" + }, + "@std/cli@1.0.6": { + "integrity": "d22d8b38c66c666d7ad1f2a66c5b122da1704f985d3c47f01129f05abb6c5d3d" + }, + "@std/encoding@1.0.5": { + "integrity": "ecf363d4fc25bd85bd915ff6733a7e79b67e0e7806334af15f4645c569fefc04" + }, + "@std/fmt@0.223.0": { + "integrity": "6deb37794127dfc7d7bded2586b9fc6f5d50e62a8134846608baf71ffc1a5208" + }, + "@std/fmt@1.0.3": { + "integrity": "97765c16aa32245ff4e2204ecf7d8562496a3cb8592340a80e7e554e0bb9149f" + }, + "@std/fs@0.223.0": { + "integrity": "3b4b0550b2c524cbaaa5a9170c90e96cbb7354e837ad1bdaf15fc9df1ae9c31c" + }, + "@std/fs@1.0.5": { + "integrity": "41806ad6823d0b5f275f9849a2640d87e4ef67c51ee1b8fb02426f55e02fd44e", + "dependencies": [ + "jsr:@std/path@^1.0.7" + ] + }, + "@std/http@1.0.9": { + "integrity": "d409fc319a5e8d4a154e576c758752e9700282d74f31357a12fec6420f9ecb6c", + "dependencies": [ + "jsr:@std/cli", + "jsr:@std/encoding", + "jsr:@std/fmt@^1.0.3", + "jsr:@std/media-types@^1.0.3", + "jsr:@std/net", + "jsr:@std/path@^1.0.7", + "jsr:@std/streams" + ] + }, + "@std/io@0.223.0": { + "integrity": "2d8c3c2ab3a515619b90da2c6ff5ea7b75a94383259ef4d02116b228393f84f1", + "dependencies": [ + "jsr:@std/assert", + "jsr:@std/bytes@0.223" + ] + }, + "@std/media-types@1.0.3": { + "integrity": "b12d30a7852f7578f4d210622df713bbfd1cbdd9b4ec2eaf5c1845ab70bab159" + }, + "@std/net@1.0.4": { + "integrity": "2f403b455ebbccf83d8a027d29c5a9e3a2452fea39bb2da7f2c04af09c8bc852" + }, + "@std/path@0.223.0": { + "integrity": "593963402d7e6597f5a6e620931661053572c982fc014000459edc1f93cc3989", + "dependencies": [ + "jsr:@std/assert" + ] + }, + "@std/path@1.0.7": { + "integrity": "76a689e07f0e15dcc6002ec39d0866797e7156629212b28f27179b8a5c3b33a1" + }, + "@std/streams@1.0.7": { + "integrity": "1a93917ca0c58c01b2bfb93647189229b1702677f169b6fb61ad6241cd2e499b" + } + }, + "npm": { + "@babel/helper-string-parser@7.25.9": { + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==" + }, + "@babel/helper-validator-identifier@7.25.9": { + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==" + }, + "@babel/parser@7.26.1": { + "integrity": "sha512-reoQYNiAJreZNsJzyrDNzFQ+IQ5JFiIzAHJg9bn94S3l+4++J7RsIhNMoB+lgP/9tpmiAQqspv+xfdxTSzREOw==", + "dependencies": [ + "@babel/types" + ] + }, + "@babel/types@7.26.0": { + "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==", + "dependencies": [ + "@babel/helper-string-parser", + "@babel/helper-validator-identifier" + ] + }, + "@jridgewell/sourcemap-codec@1.5.0": { + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + }, + "@stock3/auth-js@4.2.3": { + "integrity": "sha512-zGtenGSxx/PVfbd9oIPPyPA9K2kOWYZ382lSNFZ2JzdB8SBVZinMP5c5s406cnxgMujTpim9lpaY/o7nUUCF1w==", + "dependencies": [ + "bg-api-authorization" + ] + }, + "@stock3/koala@15.3.8-esm.0_@stock3+auth-js@4.2.3_bg-auth-legacy@2.5.0_bg-status-js@2.4.3_flora-client-js@0.5.3_m-gate@2.12.8_vue@3.5.12_vue-router@4.4.5__vue@3.5.12": { + "integrity": "sha512-7VUztN6HIRYVgUjhouR3uBlZmLcQrvt7Z2ZVidb5DvSPRFtpYxGq65fqpovR+8O8k3d8BWs338Vc9sdPBYEV4A==", + "dependencies": [ + "@stock3/auth-js", + "bg-auth-legacy", + "bg-status-js", + "flora-client-js", + "m-gate", + "vue", + "vue-router" + ] + }, + "@types/node@22.5.4": { + "integrity": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==", + "dependencies": [ + "undici-types" + ] + }, + "@vue/compiler-core@3.5.12": { + "integrity": "sha512-ISyBTRMmMYagUxhcpyEH0hpXRd/KqDU4ymofPgl2XAkY9ZhQ+h0ovEZJIiPop13UmR/54oA2cgMDjgroRelaEw==", + "dependencies": [ + "@babel/parser", + "@vue/shared", + "entities", + "estree-walker", + "source-map-js" + ] + }, + "@vue/compiler-dom@3.5.12": { + "integrity": "sha512-9G6PbJ03uwxLHKQ3P42cMTi85lDRvGLB2rSGOiQqtXELat6uI4n8cNz9yjfVHRPIu+MsK6TE418Giruvgptckg==", + "dependencies": [ + "@vue/compiler-core", + "@vue/shared" + ] + }, + "@vue/compiler-sfc@3.5.12": { + "integrity": "sha512-2k973OGo2JuAa5+ZlekuQJtitI5CgLMOwgl94BzMCsKZCX/xiqzJYzapl4opFogKHqwJk34vfsaKpfEhd1k5nw==", + "dependencies": [ + "@babel/parser", + "@vue/compiler-core", + "@vue/compiler-dom", + "@vue/compiler-ssr", + "@vue/shared", + "estree-walker", + "magic-string", + "postcss", + "source-map-js" + ] + }, + "@vue/compiler-ssr@3.5.12": { + "integrity": "sha512-eLwc7v6bfGBSM7wZOGPmRavSWzNFF6+PdRhE+VFJhNCgHiF8AM7ccoqcv5kBXA2eWUfigD7byekvf/JsOfKvPA==", + "dependencies": [ + "@vue/compiler-dom", + "@vue/shared" + ] + }, + "@vue/devtools-api@6.6.4": { + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==" + }, + "@vue/reactivity@3.5.12": { + "integrity": "sha512-UzaN3Da7xnJXdz4Okb/BGbAaomRHc3RdoWqTzlvd9+WBR5m3J39J1fGcHes7U3za0ruYn/iYy/a1euhMEHvTAg==", + "dependencies": [ + "@vue/shared" + ] + }, + "@vue/runtime-core@3.5.12": { + "integrity": "sha512-hrMUYV6tpocr3TL3Ad8DqxOdpDe4zuQY4HPY3X/VRh+L2myQO8MFXPAMarIOSGNu0bFAjh1yBkMPXZBqCk62Uw==", + "dependencies": [ + "@vue/reactivity", + "@vue/shared" + ] + }, + "@vue/runtime-dom@3.5.12": { + "integrity": "sha512-q8VFxR9A2MRfBr6/55Q3umyoN7ya836FzRXajPB6/Vvuv0zOPL+qltd9rIMzG/DbRLAIlREmnLsplEF/kotXKA==", + "dependencies": [ + "@vue/reactivity", + "@vue/runtime-core", + "@vue/shared", + "csstype" + ] + }, + "@vue/server-renderer@3.5.12_vue@3.5.12": { + "integrity": "sha512-I3QoeDDeEPZm8yR28JtY+rk880Oqmj43hreIBVTicisFTx/Dl7JpG72g/X7YF8hnQD3IFhkky5i2bPonwrTVPg==", + "dependencies": [ + "@vue/compiler-ssr", + "@vue/shared", + "vue" + ] + }, + "@vue/shared@3.5.12": { + "integrity": "sha512-L2RPSAwUFbgZH20etwrXyVyCBu9OxRSi8T/38QsvnkJyvq2LufW2lDCOzm7t/U9C1mkhJGWYfCuFBCmIuNivrg==" + }, + "bg-api-authorization@2.0.0": { + "integrity": "sha512-eo4lPdyktT3S2i6Ef+1drJuHku3NyvhLzM3JNkRsS70v+0J7C2jrsGQAXTVLnaJ5V+tC51g8C6BoanwQxi//8Q==" + }, + "bg-auth-legacy@2.5.0": { + "integrity": "sha512-+V1vVpUDrMJB1s8CcOak4yXBXbz3oejQ16GqKyuRrqy9e43VLozaHl/Xmsj1TCm2TrB7Ha2rExnk7VLbcjFU6w==" + }, + "bg-status-js@2.4.3": { + "integrity": "sha512-Ys0rGJGDZuPAfnYhTqwndRtZYxhmGopDZ2t42OGgJXnYxaZT1dDaKV56tXf75tMO9+y0PIOewP6kEgkkSccN1g==" + }, + "csstype@3.1.3": { + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "entities@4.5.0": { + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==" + }, + "estree-walker@2.0.2": { + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + }, + "flora-client-js@0.5.3": { + "integrity": "sha512-00CHCjfIDxo+/ROQkHGqS+9mzhGVmdEMErmwBg7roYD4gIKNjDgFJgYoDB8V1VmTeK4LFaPm2B1du1iMxgY8sQ==", + "dependencies": [ + "has" + ] + }, + "has@1.0.4": { + "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==" + }, + "m-gate@2.12.8": { + "integrity": "sha512-QAyDRBBYFx6k+WoVMpGwWFf2Z554LMNfF6yVmqW92FgP5hx9qUQypWZPl9P2XEw3Htlv/rBVQ9q9n+uBcx6yEg==" + }, + "magic-string@0.30.12": { + "integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==", + "dependencies": [ + "@jridgewell/sourcemap-codec" + ] + }, + "nanoid@3.3.7": { + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==" + }, + "picocolors@1.1.1": { + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + }, + "postcss@8.4.47": { + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", + "dependencies": [ + "nanoid", + "picocolors", + "source-map-js" + ] + }, + "source-map-js@1.2.1": { + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==" + }, + "undici-types@6.19.8": { + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" + }, + "vue-router@4.4.5_vue@3.5.12": { + "integrity": "sha512-4fKZygS8cH1yCyuabAXGUAsyi1b2/o/OKgu/RUb+znIYOxPRxdkytJEx+0wGcpBE1pX6vUgh5jwWOKRGvuA/7Q==", + "dependencies": [ + "@vue/devtools-api", + "vue" + ] + }, + "vue@3.5.12": { + "integrity": "sha512-CLVZtXtn2ItBIi/zHZ0Sg1Xkb7+PU32bJJ8Bmy7ts3jxXTcbfsEfBivFYYWz1Hur+lalqGAh65Coin0r+HRUfg==", + "dependencies": [ + "@vue/compiler-dom", + "@vue/compiler-sfc", + "@vue/runtime-dom", + "@vue/server-renderer", + "@vue/shared" + ] + } + }, + "workspace": { + "dependencies": [ + "npm:@stock3/koala@^15.3.8-esm.0", + "npm:vue@*", + "npm:vue@^3.5.12" + ] + } +} diff --git a/deps.ts b/deps.ts new file mode 100644 index 0000000..fca492a --- /dev/null +++ b/deps.ts @@ -0,0 +1,5 @@ +import "jsr:@deno/emit"; +import "jsr:@std/media-types"; +import "jsr:@std/http"; +import "vue"; +import "@stock3/koala"; diff --git a/main.ts b/main.ts new file mode 100644 index 0000000..9e9b28f --- /dev/null +++ b/main.ts @@ -0,0 +1,42 @@ +import { serveFile } from "jsr:@std/http/file-server"; +import { createSSRApp } from "vue"; +import { renderToString } from "vue/server-renderer"; +import App from "@/App.tsx"; +import transpileResponse from './transpileTs.ts'; + +const utf8Decoder = new TextDecoder("utf-8"); + +Deno.serve({ + port: 8080, + hostname: "0.0.0.0", + onListen({ port, hostname }) { + console.log(`Listening on port http://${hostname}:${port}/`); + }, +}, async (req, _conn) => { + if (req.method === "GET") { + const pathname = URL.parse(req.url)?.pathname ?? "/"; + if (pathname === "/") { + const rendered = await renderToString(createSSRApp(App)); + const content = utf8Decoder.decode(await Deno.readFile("./playground/index.html")) + .replace(``, rendered) + .replace(``, ''); + return new Response(content, { headers: { "Content-Type": "text/html" } }); + } else if (pathname === "/health") { + return new Response("OK"); + } else if (pathname.startsWith('/app') && (pathname.endsWith('.ts') || pathname.endsWith('.tsx'))) { + const response = await serveFile(req, './' + pathname); + return await transpileResponse(response, req.url, pathname); + } else if (pathname.startsWith('/deps')) { + return serveFile(req, `node_modules/${pathname.split('/deps')[1]}`); + } else { + return serveFile(req, `playground${pathname}`); + } + } else { + return new Response("Only GET allowed.", { status: 500 }); + } +}); + +Deno.addSignalListener("SIGINT", () => { + console.info("Shutting down (received SIGINT)"); + Deno.exit(); +}); diff --git a/public/app.js b/public/app.js new file mode 100644 index 0000000..9833426 --- /dev/null +++ b/public/app.js @@ -0,0 +1,4 @@ +import { createSSRApp } from "vue"; +import App from "@/App.tsx"; + +createSSRApp(App).mount('#app-root'); diff --git a/public/icon.webp b/public/icon.webp new file mode 100644 index 0000000000000000000000000000000000000000..9658d7ea8d3bc908e3b2d352b172cfe305e6c269 GIT binary patch literal 23822 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 RTN3epiid{>p!I6u{{Wwh;Ise$ literal 0 HcmV?d00001 diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..e97930e --- /dev/null +++ b/public/index.html @@ -0,0 +1,27 @@ + + + + G'day + + + + + + + +
+

G'day, mate!

+

Willkommen auf Daniels Spielwiese

+ KANGAROO +
+
+ + diff --git a/public/styles.css b/public/styles.css new file mode 100644 index 0000000..ef76dde --- /dev/null +++ b/public/styles.css @@ -0,0 +1,22 @@ +.container { + margin: auto; + text-align: center; + width: 100%; + background-color: #fffafa; + box-shadow: #000000; + padding-top: 10px; + min-height: calc(100vh - 10px); + box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.2); + + @media (min-width: 992px) { + width: 900px; + } + + h1 { + margin: 0; + } +} + +body { + margin: 0; +} diff --git a/transpileTs.ts b/transpileTs.ts new file mode 100644 index 0000000..b758fa7 --- /dev/null +++ b/transpileTs.ts @@ -0,0 +1,80 @@ +import { contentType } from "jsr:@std/media-types"; +import { transpile } from "jsr:@deno/emit"; +import config from "./deno.json" with { type: "json" }; + +const jsContentType = contentType(".js"); + +export enum MediaType { + TypeScript, + JSX, + TSX, +}; + +// https://github.com/denoland/deno_ast/blob/ea1ccec37e1aa8e5e1e70f983a7ed1472d0e132a/src/media_type.rs#L117 +const customContentType = { + [MediaType.TypeScript]: "text/typescript; charset=utf-8", + [MediaType.JSX]: "text/jsx; charset=utf-8", + [MediaType.TSX]: "text/tsx; charset=utf-8", +}; + +async function rewriteTsResponse(response: Response, url: URL, mediaType: MediaType) { + const tsCode = await response.text(); + const targetUrlStr = url.toString(); + try { + const result = await transpile(url, { + importMap: config, + compilerOptions: config.compilerOptions, + load(specifier) { + if (specifier !== targetUrlStr) { + return Promise.resolve({ + kind: "module", + specifier, + content: "", + headers: { "content-type": "application/javascript; charset=utf-8" }, + }); + } else { + return Promise.resolve({ + kind: "module", + specifier, + content: tsCode, + headers: { + "content-type": customContentType[mediaType], + }, + }); + } + }, + }); + const jsCode = result.get(targetUrlStr); + const { headers } = response; + headers.set("content-type", jsContentType); + headers.delete("content-length"); + + return new Response(jsCode, { + status: response.status, + statusText: response.statusText, + headers, + }); + } catch (e) { + console.error(e); + return new Response(`${e}`, { + status: 500, + statusText: `${e}`, + headers: response.headers, + }); + } +} + +export default async function transpileResponse(response: Response, requestUrl: string, filepath?: string): Promise { + const url = new URL(`ts-serve:///${ requestUrl }`); + if (response.status !== 200) { + return response; + } + const pathname = filepath !== undefined ? filepath : url.pathname; + const extension = pathname.split('.').at(-1) ?? null; + switch (extension) { + case 'ts': return await rewriteTsResponse(response, url, MediaType.TypeScript); + case 'tsx': return await rewriteTsResponse(response, url, MediaType.TSX); + case 'jsx': return await rewriteTsResponse(response, url, MediaType.JSX); + default: return response; + } +}