diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index ab36117..f7a5a7a 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -41,11 +41,11 @@ jobs: run: deno task check - name: Build - run: deno task css + run: deno task build - name: Deploy uses: denoland/deployctl@v1 with: project: "mage-docs" - entrypoint: "./src/main.tsx" + entrypoint: "./src/serve.ts" root: "." diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f9dfa58..a11914f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,4 +35,4 @@ jobs: run: deno task check - name: Build - run: deno task css + run: deno task build diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2877c94..b91da8d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -31,16 +31,6 @@ The repository contains a Mage Server application. When making changes to the server in the [src](./src) directory, it is recommended to run the server locally to test the changes. -The styles are powered by [tailwindcss](https://tailwindcss.com/) and are build -using the tailwind CLI. To build the styles run the following command: - -```sh -deno task css - -# or in watch mode: -deno task css --watch -``` - Run the server with the following command: ```sh diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..0e441a4 --- /dev/null +++ b/TODO.md @@ -0,0 +1,6 @@ +# To do + +1. Make build id configurable via optional param to MageApp contructor, default + to guid +2. Add the asset signals api into @mage/preact, it can grab the build if off + context and set it on every render for the assetURL to use diff --git a/deno.json b/deno.json index e084e7a..19f6386 100644 --- a/deno.json +++ b/deno.json @@ -1,21 +1,20 @@ { "tasks": { - "dev": "deno run --allow-all --watch ./src/main.tsx", - "css": "deno run --allow-all npm:@tailwindcss/cli -i ./src/main.css -o ./public/main.css --minify", + "build": "deno run -A ./src/build.ts", + "dev": "deno run -A --watch ./src/develop.ts", "lint": "deno lint", "format": "deno fmt", "check": "deno check ." }, "imports": { - "@mage/app": "jsr:@mage/app@^0.4.0", - "@mage/preact": "jsr:@mage/preact@^0.1.4", + "@heroicons/react": "npm:@heroicons/react@^2.2.0", + "@mage/app": "jsr:@mage/app@^0.7.1", + "@mage/preact": "jsr:@mage/preact@^0.2.0", + "@mage/tailwindcss": "jsr:@mage/tailwindcss@^0.2.4", "@preact-icons/fa": "jsr:@preact-icons/fa@^1.0.12", - "@std/path": "jsr:@std/path@^1.0.8", - "@tailwindcss/cli": "npm:@tailwindcss/cli@^4.0.3", - "@tailwindcss/postcss": "npm:@tailwindcss/postcss@^4.0.6", - "postcss": "npm:postcss@^8.5.2", - "preact": "npm:preact@^10.26.0", - "tailwindcss": "npm:tailwindcss@^4.0.3" + "@preact/signals": "npm:@preact/signals@^2.0.1", + "preact": "npm:preact@^10.26.2", + "tailwindcss": "npm:tailwindcss@^4.0.8" }, "compilerOptions": { "jsx": "react-jsx", diff --git a/deno.lock b/deno.lock index 9da1c1d..b4e484c 100644 --- a/deno.lock +++ b/deno.lock @@ -1,12 +1,14 @@ { "version": "4", "specifiers": { - "jsr:@mage/app@0.4": "0.4.0", - "jsr:@mage/preact@~0.1.4": "0.1.4", + "jsr:@mage/app@~0.6.1": "0.6.3", + "jsr:@mage/app@~0.7.1": "0.7.1", + "jsr:@mage/preact@0.2": "0.2.0", + "jsr:@mage/tailwindcss@~0.2.4": "0.2.4", "jsr:@preact-icons/common@^1.0.12": "1.0.12", "jsr:@preact-icons/fa@^1.0.12": "1.0.12", "jsr:@std/cache@~0.1.3": "0.1.3", - "jsr:@std/cli@^1.0.12": "1.0.12", + "jsr:@std/cli@^1.0.12": "1.0.13", "jsr:@std/encoding@^1.0.7": "1.0.7", "jsr:@std/fmt@^1.0.5": "1.0.5", "jsr:@std/fs@^1.0.11": "1.0.13", @@ -14,42 +16,56 @@ "jsr:@std/http@^1.0.13": "1.0.13", "jsr:@std/media-types@^1.1.0": "1.1.0", "jsr:@std/net@^1.0.4": "1.0.4", - "jsr:@std/path@*": "1.0.8", "jsr:@std/path@^1.0.8": "1.0.8", "jsr:@std/streams@^1.0.9": "1.0.9", - "npm:@tailwindcss/cli@^4.0.3": "4.0.6", - "npm:@tailwindcss/postcss@^4.0.6": "4.0.6", - "npm:postcss@^8.5.2": "8.5.2", - "npm:preact-render-to-string@^6.5.13": "6.5.13_preact@10.26.0", + "npm:@heroicons/react@^2.2.0": "2.2.0_react@18.3.1", + "npm:@preact/signals@^2.0.1": "2.0.1_preact@10.26.2", + "npm:@tailwindcss/cli@*": "4.0.8", + "npm:preact-render-to-string@^6.5.13": "6.5.13_preact@10.22.1", "npm:preact@10.22.1": "10.22.1", - "npm:preact@^10.22.1": "10.26.0", - "npm:preact@^10.25.4": "10.26.0", - "npm:preact@^10.26.0": "10.26.0", - "npm:tailwindcss@^4.0.3": "4.0.6" + "npm:preact@^10.22.1": "10.26.2", + "npm:preact@^10.25.4": "10.26.2", + "npm:preact@^10.26.2": "10.26.2", + "npm:tailwindcss@^4.0.8": "4.0.8" }, "jsr": { - "@mage/app@0.4.0": { - "integrity": "a378a5e15c2c5c36df94ee880b6180c515dec0e03825331a5d63308504d3855e", + "@mage/app@0.6.3": { + "integrity": "55d1bf54795a1cec555d8a028df6e7d1e4ed3664cafbba2ac9298178d836a51d", + "dependencies": [ + "jsr:@std/cache", + "jsr:@std/http" + ] + }, + "@mage/app@0.7.1": { + "integrity": "9dd58b2d762a1f8c485da7aef2ddb3cf622578b5de84f1dbf19b4c04d30fdb2b", "dependencies": [ "jsr:@std/cache", "jsr:@std/fs", "jsr:@std/http", - "jsr:@std/path@^1.0.8" + "jsr:@std/path" ] }, - "@mage/preact@0.1.4": { - "integrity": "2c819efefe81cb035dd3898a7f80397031e7d54df51597d9f28ddcf6ff887890", + "@mage/preact@0.2.0": { + "integrity": "608e52edd0c50597219094f340eddd763eaec185c59a0ba1b6904561db806837", "dependencies": [ - "jsr:@mage/app", + "jsr:@mage/app@~0.6.1", + "npm:@preact/signals", "npm:preact-render-to-string", "npm:preact@^10.25.4" ] }, + "@mage/tailwindcss@0.2.4": { + "integrity": "6aba6f6c48301bc3563e790e8f340dc5be72718511b64d9e1b5bcb551d72dbbf", + "dependencies": [ + "jsr:@mage/app@~0.7.1", + "jsr:@std/path" + ] + }, "@preact-icons/common@1.0.12": { "integrity": "f7d7329d55c2753b0162438b120b638e5058fa406f49fe6b422e3b0694f6e0c1", "dependencies": [ "npm:preact@^10.22.1", - "npm:preact@^10.26.0" + "npm:preact@^10.26.2" ] }, "@preact-icons/fa@1.0.12": { @@ -62,8 +78,8 @@ "@std/cache@0.1.3": { "integrity": "8d3ab61d994d0915295048999f34a8ce2280f0e4d1f4cccb08c9e3d297c0c6ec" }, - "@std/cli@1.0.12": { - "integrity": "e5cfb7814d189da174ecd7a34fbbd63f3513e24a1b307feb2fcd5da47a070d90" + "@std/cli@1.0.13": { + "integrity": "5db2d95ab2dca3bca9fb6ad3c19908c314e93d6391c8b026725e4892d4615a69" }, "@std/encoding@1.0.7": { "integrity": "f631247c1698fef289f2de9e2a33d571e46133b38d042905e3eac3715030a82d" @@ -74,7 +90,7 @@ "@std/fs@1.0.13": { "integrity": "756d3ff0ade91c9e72b228e8012b6ff00c3d4a4ac9c642c4dac083536bf6c605", "dependencies": [ - "jsr:@std/path@^1.0.8" + "jsr:@std/path" ] }, "@std/html@1.0.3": { @@ -89,7 +105,7 @@ "jsr:@std/html", "jsr:@std/media-types", "jsr:@std/net", - "jsr:@std/path@^1.0.8", + "jsr:@std/path", "jsr:@std/streams" ] }, @@ -107,8 +123,11 @@ } }, "npm": { - "@alloc/quick-lru@5.2.0": { - "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==" + "@heroicons/react@2.2.0_react@18.3.1": { + "integrity": "sha512-LMcepvRaS9LYHJGsF0zzmgKCUim/X3N/DQKc4jepAXJ7l8QxJ1PmxJzqplF2Z3FE4PqBAIGyJAQ/w4B5dsqbtQ==", + "dependencies": [ + "react" + ] }, "@parcel/watcher-android-arm64@2.5.1": { "integrity": "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==" @@ -171,8 +190,18 @@ "node-addon-api" ] }, - "@tailwindcss/cli@4.0.6": { - "integrity": "sha512-5EybaKjLL6ruuKq4PFMpf60npR6x6MmVlqvXWca7ZcujQd7rj5vckNHi2M7Bn0U7dkWmmOm3s/9USLL7BZuudw==", + "@preact/signals-core@1.8.0": { + "integrity": "sha512-OBvUsRZqNmjzCZXWLxkZfhcgT+Fk8DDcT/8vD6a1xhDemodyy87UJRJfASMuSD8FaAIeGgGm85ydXhm7lr4fyA==" + }, + "@preact/signals@2.0.1_preact@10.26.2": { + "integrity": "sha512-f9p/utMgttPb9bJ+UgRBkTDZ9uQiZfX1/gV3pXGWz+yGNQj8MrnG55Xo8MAG4IHcb5UXQO6tvt9ZlsM4A2j+Rw==", + "dependencies": [ + "@preact/signals-core", + "preact@10.26.2" + ] + }, + "@tailwindcss/cli@4.0.8": { + "integrity": "sha512-nFN0QjibH8Yhd028TP+WnStfEG0Bw9uS8ojqJNeEo4RfXH8Mfi42Y9lvhl3yPcii8/xt0/Mq/kZywjvpkcgLJg==", "dependencies": [ "@parcel/watcher", "@tailwindcss/node", @@ -184,49 +213,49 @@ "tailwindcss" ] }, - "@tailwindcss/node@4.0.6": { - "integrity": "sha512-jb6E0WeSq7OQbVYcIJ6LxnZTeC4HjMvbzFBMCrQff4R50HBlo/obmYNk6V2GCUXDeqiXtvtrQgcIbT+/boB03Q==", + "@tailwindcss/node@4.0.8": { + "integrity": "sha512-FKArQpbrbwv08TNT0k7ejYXpF+R8knZFAatNc0acOxbgeqLzwb86r+P3LGOjIeI3Idqe9CVkZrh4GlsJLJKkkw==", "dependencies": [ "enhanced-resolve", "jiti", "tailwindcss" ] }, - "@tailwindcss/oxide-android-arm64@4.0.6": { - "integrity": "sha512-xDbym6bDPW3D2XqQqX3PjqW3CKGe1KXH7Fdkc60sX5ZLVUbzPkFeunQaoP+BuYlLc2cC1FoClrIRYnRzof9Sow==" + "@tailwindcss/oxide-android-arm64@4.0.8": { + "integrity": "sha512-We7K79+Sm4mwJHk26Yzu/GAj7C7myemm7PeXvpgMxyxO70SSFSL3uCcqFbz9JA5M5UPkrl7N9fkBe/Y0iazqpA==" }, - "@tailwindcss/oxide-darwin-arm64@4.0.6": { - "integrity": "sha512-1f71/ju/tvyGl5c2bDkchZHy8p8EK/tDHCxlpYJ1hGNvsYihZNurxVpZ0DefpN7cNc9RTT8DjrRoV8xXZKKRjg==" + "@tailwindcss/oxide-darwin-arm64@4.0.8": { + "integrity": "sha512-Lv9Isi2EwkCTG1sRHNDi0uRNN1UGFdEThUAGFrydRmQZnraGLMjN8gahzg2FFnOizDl7LB2TykLUuiw833DSNg==" }, - "@tailwindcss/oxide-darwin-x64@4.0.6": { - "integrity": "sha512-s/hg/ZPgxFIrGMb0kqyeaqZt505P891buUkSezmrDY6lxv2ixIELAlOcUVTkVh245SeaeEiUVUPiUN37cwoL2g==" + "@tailwindcss/oxide-darwin-x64@4.0.8": { + "integrity": "sha512-fWfywfYIlSWtKoqWTjukTHLWV3ARaBRjXCC2Eo0l6KVpaqGY4c2y8snUjp1xpxUtpqwMvCvFWFaleMoz1Vhzlw==" }, - "@tailwindcss/oxide-freebsd-x64@4.0.6": { - "integrity": "sha512-Z3Wo8FWZnmio8+xlcbb7JUo/hqRMSmhQw8IGIRoRJ7GmLR0C+25Wq+bEX/135xe/yEle2lFkhu9JBHd4wZYiig==" + "@tailwindcss/oxide-freebsd-x64@4.0.8": { + "integrity": "sha512-SO+dyvjJV9G94bnmq2288Ke0BIdvrbSbvtPLaQdqjqHR83v5L2fWADyFO+1oecHo9Owsk8MxcXh1agGVPIKIqw==" }, - "@tailwindcss/oxide-linux-arm-gnueabihf@4.0.6": { - "integrity": "sha512-SNSwkkim1myAgmnbHs4EjXsPL7rQbVGtjcok5EaIzkHkCAVK9QBQsWeP2Jm2/JJhq4wdx8tZB9Y7psMzHYWCkA==" + "@tailwindcss/oxide-linux-arm-gnueabihf@4.0.8": { + "integrity": "sha512-ZSHggWiEblQNV69V0qUK5vuAtHP+I+S2eGrKGJ5lPgwgJeAd6GjLsVBN+Mqn2SPVfYM3BOpS9jX/zVg9RWQVDQ==" }, - "@tailwindcss/oxide-linux-arm64-gnu@4.0.6": { - "integrity": "sha512-tJ+mevtSDMQhKlwCCuhsFEFg058kBiSy4TkoeBG921EfrHKmexOaCyFKYhVXy4JtkaeeOcjJnCLasEeqml4i+Q==" + "@tailwindcss/oxide-linux-arm64-gnu@4.0.8": { + "integrity": "sha512-xWpr6M0OZLDNsr7+bQz+3X7zcnDJZJ1N9gtBWCtfhkEtDjjxYEp+Lr5L5nc/yXlL4MyCHnn0uonGVXy3fhxaVA==" }, - "@tailwindcss/oxide-linux-arm64-musl@4.0.6": { - "integrity": "sha512-IoArz1vfuTR4rALXMUXI/GWWfx2EaO4gFNtBNkDNOYhlTD4NVEwE45nbBoojYiTulajI4c2XH8UmVEVJTOJKxA==" + "@tailwindcss/oxide-linux-arm64-musl@4.0.8": { + "integrity": "sha512-5tz2IL7LN58ssGEq7h/staD7pu/izF/KeMWdlJ86WDe2Ah46LF3ET6ZGKTr5eZMrnEA0M9cVFuSPprKRHNgjeg==" }, - "@tailwindcss/oxide-linux-x64-gnu@4.0.6": { - "integrity": "sha512-QtsUfLkEAeWAC3Owx9Kg+7JdzE+k9drPhwTAXbXugYB9RZUnEWWx5x3q/au6TvUYcL+n0RBqDEO2gucZRvRFgQ==" + "@tailwindcss/oxide-linux-x64-gnu@4.0.8": { + "integrity": "sha512-KSzMkhyrxAQyY2o194NKVKU9j/c+NFSoMvnHWFaNHKi3P1lb+Vq1UC19tLHrmxSkKapcMMu69D7+G1+FVGNDXQ==" }, - "@tailwindcss/oxide-linux-x64-musl@4.0.6": { - "integrity": "sha512-QthvJqIji2KlGNwLcK/PPYo7w1Wsi/8NK0wAtRGbv4eOPdZHkQ9KUk+oCoP20oPO7i2a6X1aBAFQEL7i08nNMA==" + "@tailwindcss/oxide-linux-x64-musl@4.0.8": { + "integrity": "sha512-yFYKG5UtHTRimjtqxUWXBgI4Tc6NJe3USjRIVdlTczpLRxq/SFwgzGl5JbatCxgSRDPBFwRrNPxq+ukfQFGdrw==" }, - "@tailwindcss/oxide-win32-arm64-msvc@4.0.6": { - "integrity": "sha512-+oka+dYX8jy9iP00DJ9Y100XsqvbqR5s0yfMZJuPR1H/lDVtDfsZiSix1UFBQ3X1HWxoEEl6iXNJHWd56TocVw==" + "@tailwindcss/oxide-win32-arm64-msvc@4.0.8": { + "integrity": "sha512-tndGujmCSba85cRCnQzXgpA2jx5gXimyspsUYae5jlPyLRG0RjXbDshFKOheVXU4TLflo7FSG8EHCBJ0EHTKdQ==" }, - "@tailwindcss/oxide-win32-x64-msvc@4.0.6": { - "integrity": "sha512-+o+juAkik4p8Ue/0LiflQXPmVatl6Av3LEZXpBTfg4qkMIbZdhCGWFzHdt2NjoMiLOJCFDddoV6GYaimvK1Olw==" + "@tailwindcss/oxide-win32-x64-msvc@4.0.8": { + "integrity": "sha512-T77jroAc0p4EHVVgTUiNeFn6Nj3jtD3IeNId2X+0k+N1XxfNipy81BEkYErpKLiOkNhpNFjPee8/ZVas29b2OQ==" }, - "@tailwindcss/oxide@4.0.6": { - "integrity": "sha512-lVyKV2y58UE9CeKVcYykULe9QaE1dtKdxDEdrTPIdbzRgBk6bdxHNAoDqvcqXbIGXubn3VOl1O/CFF77v/EqSA==", + "@tailwindcss/oxide@4.0.8": { + "integrity": "sha512-KfMcuAu/Iw+DcV1e8twrFyr2yN8/ZDC/odIGta4wuuJOGkrkHZbvJvRNIbQNhGh7erZTYV6Ie0IeD6WC9Y8Hcw==", "dependencies": [ "@tailwindcss/oxide-android-arm64", "@tailwindcss/oxide-darwin-arm64", @@ -241,17 +270,6 @@ "@tailwindcss/oxide-win32-x64-msvc" ] }, - "@tailwindcss/postcss@4.0.6": { - "integrity": "sha512-noTaGPHjGCXTCc487TWnfAEN0VMjqDAecssWDOsfxV2hFrcZR0AHthX7IdY/0xHTg/EtpmIPdssddlZ5/B7JnQ==", - "dependencies": [ - "@alloc/quick-lru", - "@tailwindcss/node", - "@tailwindcss/oxide", - "lightningcss", - "postcss", - "tailwindcss" - ] - }, "braces@3.0.3": { "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dependencies": [ @@ -292,6 +310,9 @@ "jiti@2.4.2": { "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==" }, + "js-tokens@4.0.0": { + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, "lightningcss-darwin-arm64@1.29.1": { "integrity": "sha512-HtR5XJ5A0lvCqYAoSv2QdZZyoHNttBpa5EP9aNuzBQeKGfbyH5+UipLWvVzpP4Uml5ej4BYs5I9Lco9u1fECqw==" }, @@ -338,6 +359,12 @@ "lightningcss-win32-x64-msvc" ] }, + "loose-envify@1.4.0": { + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": [ + "js-tokens" + ] + }, "micromatch@4.0.8": { "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dependencies": [ @@ -348,9 +375,6 @@ "mri@1.2.0": { "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==" }, - "nanoid@3.3.8": { - "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==" - }, "node-addon-api@7.1.1": { "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==" }, @@ -360,31 +384,26 @@ "picomatch@2.3.1": { "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" }, - "postcss@8.5.2": { - "integrity": "sha512-MjOadfU3Ys9KYoX0AdkBlFEF1Vx37uCCeN4ZHnmwm9FfpbsGWMZeBLMmmpY+6Ocqod7mkdZ0DT31OlbsFrLlkA==", - "dependencies": [ - "nanoid", - "picocolors", - "source-map-js" - ] - }, - "preact-render-to-string@6.5.13_preact@10.26.0": { + "preact-render-to-string@6.5.13_preact@10.22.1": { "integrity": "sha512-iGPd+hKPMFKsfpR2vL4kJ6ZPcFIoWZEcBf0Dpm3zOpdVvj77aY8RlLiQji5OMrngEyaxGogeakTb54uS2FvA6w==", "dependencies": [ - "preact@10.26.0" + "preact@10.22.1" ] }, "preact@10.22.1": { "integrity": "sha512-jRYbDDgMpIb5LHq3hkI0bbl+l/TQ9UnkdQ0ww+lp+4MMOdqaUYdFc5qeyP+IV8FAd/2Em7drVPeKdQxsiWCf/A==" }, - "preact@10.26.0": { - "integrity": "sha512-6ugi/Mb7lyV5RA6KlnijFyDLMU253i7L0RRiObIzDoqj59KT9iTeNJbA/YGw6M7jP4vxaab0DOA8DgodTOA6EQ==" + "preact@10.26.2": { + "integrity": "sha512-0gNmv4qpS9HaN3+40CLBAnKe0ZfyE4ZWo5xKlC1rVrr0ckkEvJvAQqKaHANdFKsGstoxrY4AItZ7kZSGVoVjgg==" }, - "source-map-js@1.2.1": { - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==" + "react@18.3.1": { + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "dependencies": [ + "loose-envify" + ] }, - "tailwindcss@4.0.6": { - "integrity": "sha512-mysewHYJKaXgNOW6pp5xon/emCsfAMnO8WMaGKZZ35fomnR/T5gYnRg2/yRTTrtXiEl1tiVkeRt0eMO6HxEZqw==" + "tailwindcss@4.0.8": { + "integrity": "sha512-Me7N5CKR+D2A1xdWA5t5+kjjT7bwnxZOE6/yDI/ixJdJokszsn2n++mdU5yJwrsTpqFX2B9ZNMBJDwcqk9C9lw==" }, "tapable@2.2.1": { "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==" @@ -398,15 +417,14 @@ }, "workspace": { "dependencies": [ - "jsr:@mage/app@0.4", - "jsr:@mage/preact@~0.1.4", + "jsr:@mage/app@~0.7.1", + "jsr:@mage/preact@0.2", + "jsr:@mage/tailwindcss@~0.2.4", "jsr:@preact-icons/fa@^1.0.12", - "jsr:@std/path@^1.0.8", - "npm:@tailwindcss/cli@^4.0.3", - "npm:@tailwindcss/postcss@^4.0.6", - "npm:postcss@^8.5.2", - "npm:preact@^10.26.0", - "npm:tailwindcss@^4.0.3" + "npm:@heroicons/react@^2.2.0", + "npm:@preact/signals@^2.0.1", + "npm:preact@^10.26.2", + "npm:tailwindcss@^4.0.8" ] } } diff --git a/src/main.tsx b/src/app.tsx similarity index 74% rename from src/main.tsx rename to src/app.tsx index c15b508..efa977d 100644 --- a/src/main.tsx +++ b/src/app.tsx @@ -1,11 +1,9 @@ import { MageApp } from "@mage/app"; -import { useSecurityHeaders } from "@mage/app/security-headers"; -import { useCSP } from "@mage/app/csp"; -import { useServeFiles } from "@mage/app/serve-files"; +import { securityHeaders } from "@mage/app/security-headers"; +import { csp } from "@mage/app/csp"; +import { serveFiles } from "@mage/app/serve-files"; import { render } from "@mage/preact"; import { JSX } from "preact"; -import { resolve } from "jsr:@std/path"; -import { AssetProvider } from "./utils.tsx"; import { IndexPage } from "./pages/index.tsx"; import { GettingStartedPage } from "./pages/getting-started.tsx"; import { BasicsPage } from "./pages/basics.tsx"; @@ -19,14 +17,24 @@ import { ServingFilesPage } from "./pages/serving-files.tsx"; import { CORSPage } from "./pages/cors.tsx"; import { CSPPage } from "./pages/csp.tsx"; import { CacheControlPage } from "./pages/cache-control.tsx"; +import { tailwindcss } from "@mage/tailwindcss"; -const isDeployed = Boolean(Deno.env.get("DENO_DEPLOYMENT_ID")); +const isDeployed = Boolean(Deno.env.has("DENO_DEPLOYMENT_ID")); -export const app = new MageApp(); +export const app = new MageApp({ + buildId: Deno.env.get("DENO_DEPLOYMENT_ID"), +}); + +app.plugin( + tailwindcss({ + entry: "./src/main.css", + output: "./public/main.css", + }), +); app.use( - useSecurityHeaders(), - useCSP({ + securityHeaders(), + csp({ directives: { scriptSrc: [ "'self'", @@ -39,6 +47,10 @@ app.use( }), ); +app.get("/", async (c) => { + await render(c, ); +}); + const pages: [string, JSX.Element][] = [ ["/", ], ["/getting-started", ], @@ -57,13 +69,13 @@ const pages: [string, JSX.Element][] = [ for (const [path, page] of pages) { app.get(path, async (c) => { - await render(c, {page}); + await render(c, page); }); } app.get( "/public/*", - useServeFiles({ directory: resolve(Deno.cwd(), "./public") }), + serveFiles({ + directory: "./public", + }), ); - -Deno.serve(app.handler); diff --git a/src/build.ts b/src/build.ts new file mode 100644 index 0000000..4ae985b --- /dev/null +++ b/src/build.ts @@ -0,0 +1,3 @@ +import { app } from "./app.tsx"; + +app.build(); diff --git a/src/components/page.tsx b/src/components/page.tsx index 18f1932..a365f7e 100644 --- a/src/components/page.tsx +++ b/src/components/page.tsx @@ -2,7 +2,7 @@ import type { ComponentChildren } from "preact"; import { GitHub } from "./github.tsx"; import { NavList } from "./nav-list.tsx"; import { Heading } from "./heading.tsx"; -import { useAsset } from "../utils.tsx"; +import { assetURL } from "@mage/preact"; interface PageProps { children: ComponentChildren; @@ -11,8 +11,6 @@ interface PageProps { } export const Page = (props: PageProps) => { - const asset = useAsset(); - return ( @@ -20,12 +18,12 @@ export const Page = (props: PageProps) => { Mage {props.title && `| ${props.title}`} - + {/* Highlight.js */} { return ( - +
diff --git a/src/serve.ts b/src/serve.ts new file mode 100644 index 0000000..0e6a73c --- /dev/null +++ b/src/serve.ts @@ -0,0 +1,3 @@ +import { app } from "./app.tsx"; + +Deno.serve(app.handler); diff --git a/src/utils.tsx b/src/utils.tsx deleted file mode 100644 index 9b42399..0000000 --- a/src/utils.tsx +++ /dev/null @@ -1,131 +0,0 @@ -import { MageMiddleware } from "@mage/app"; -import postcss, { AcceptedPlugin } from "postcss"; -import { ComponentChildren, createContext } from "preact"; -import { useContext } from "preact/hooks"; -/** - * Options for building CSS file using PostCSS - */ -interface PostCSSOptions { - /** - * Path to the entry CSS file - */ - entry: string; - /** - * Path to the output CSS file - */ - output: string; - /** - * PostCSS plugins - */ - plugins: AcceptedPlugin[]; -} - -/** - * Build CSS file using PostCSS - * - * @param options PostCSS options - */ -export const buildPostCSS = async (options: PostCSSOptions) => { - const input = await Deno.readTextFile(options.entry); - const output = await postcss(options.plugins).process(input, { - from: options.entry, - to: options.output, - }); - - await Deno.writeTextFile(options.output, output.css); -}; - -/** - * Compile CSS file using PostCSS. The compilation will take place before the next middleware is called - * and on every request. - * - * @param options Middleware options - * @returns MageMiddleware - */ -export const usePostCSS = (options: PostCSSOptions): MageMiddleware => { - return async (_, next) => { - await buildPostCSS(options); - - await next(); - }; -}; - -/** - * Get asset URL for the provided path with the build id embedded in the url for cache busting - * - * @param buildId The build id used to cache bust the asset, `useServeFiles()` supports serving files with the build id embedded - * @param path Path to the asset - */ -export const asset = (buildId: string, path: string): string => { - const pathParts = path.split("/"); - const filename = pathParts.pop(); - - if (filename?.includes(".")) { - const filenameParts = filename.split("."); - const extension = filenameParts.pop(); - const basename = filenameParts.join("."); - pathParts.push(`${basename}${buildId}.${extension}`); - } else { - pathParts.push(`${filename}${buildId}`); - } - - return pathParts.join("/"); -}; - -/** - * Context value for asset path - */ -interface AssetContextValue { - /** - * Get the asset path with the build id injected for cache busting - * - * @param path Path to the asset - */ - asset: (path: string) => string; -} - -/** - * Context for asset function to live on - */ -const AssetContext = createContext(undefined); - -/** - * Props for AssetProvider component - */ -interface AssetProviderProps { - buildId: string; - children: ComponentChildren; -} - -/** - * AssetProvider component to provide paths to assets for the browser. - * - * @param props AssetProviderProps - * @returns JSXInternal.Element - */ -export const AssetProvider = (props: AssetProviderProps) => { - return ( - asset(props.buildId, key), - }} - > - {props.children} - - ); -}; - -/** - * Hook to get the asset path. - * - * @returns Function to get the asset path. - */ -export const useAsset = () => { - const context = useContext(AssetContext); - - if (!context) { - throw new Error("useAsset() must be used within "); - } - - return context.asset; -}; diff --git a/tailwind.config.ts b/tailwind.config.ts deleted file mode 100644 index e1d6f82..0000000 --- a/tailwind.config.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type { Config } from "tailwindcss"; - -export default { - content: ["./**/*.{html,ts,tsx}"], - theme: { - extend: { - fontFamily: { - sans: ['"Geist Mono", monospace', "system-ui", "sans-serif"], - }, - }, - }, - plugins: [], -} satisfies Config;