diff --git a/package-lock.json b/package-lock.json index ba3e446..5c121f0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,10 +12,13 @@ "@sveltejs/adapter-static": "^3.0.1", "@sveltejs/enhanced-img": "^0.1.8", "better-sqlite3": "^9.4.3", + "carbon-components-svelte": "^0.84.0", "cookie": "^0.6.0", "email-validator": "^2.0.4", "hcaptcha": "^0.1.1", "jsonwebtoken": "^9.0.2", + "prism-themes": "^1.9.0", + "prismjs": "^1.29.0", "radix-svelte": "^0.9.0", "reflect-metadata": "^0.2.1", "sequelize": "^6.37.1", @@ -34,8 +37,10 @@ "@sveltejs/adapter-node": "^5.0.1", "@sveltejs/kit": "^2.0.0", "@sveltejs/vite-plugin-svelte": "^3.0.0", + "@tailwindcss/typography": "^0.5.10", "@types/cookie": "^0.6.0", "@types/jsonwebtoken": "^9.0.6", + "@types/prismjs": "^1.26.3", "@types/uuid": "^9.0.8", "@types/ws": "^8.5.10", "autoprefixer": "^10.4.16", @@ -485,6 +490,14 @@ "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", "optional": true }, + "node_modules/@ibm/telemetry-js": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ibm/telemetry-js/-/telemetry-js-1.3.0.tgz", + "integrity": "sha512-9gIkyF2B9RizWN6rsdQN76DN6D+/Xbr4HGTwm6EUujfXvEVtWbf4jzxDFwKvZkeTC2tjHpkUNJQKdivbMKt8yg==", + "bin": { + "ibmtelemetry": "dist/collect.js" + } + }, "node_modules/@img/sharp-darwin-arm64": { "version": "0.33.2", "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.2.tgz", @@ -1542,6 +1555,34 @@ "vite": "^5.0.0" } }, + "node_modules/@tailwindcss/typography": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.10.tgz", + "integrity": "sha512-Pe8BuPJQJd3FfRnm6H0ulKIGoMEQS+Vq01R6M5aCrFB/ccR/shT+0kXLjouGC1gFLm9hopTFN+DMP0pfwRWzPw==", + "dev": true, + "dependencies": { + "lodash.castarray": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.merge": "^4.6.2", + "postcss-selector-parser": "6.0.10" + }, + "peerDependencies": { + "tailwindcss": ">=3.0.0 || insiders" + } + }, + "node_modules/@tailwindcss/typography/node_modules/postcss-selector-parser": { + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", @@ -1611,6 +1652,12 @@ "undici-types": "~5.26.4" } }, + "node_modules/@types/prismjs": { + "version": "1.26.3", + "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.3.tgz", + "integrity": "sha512-A0D0aTXvjlqJ5ZILMz3rNfDBOx9hHxLZYv2by47Sm/pqW35zzjusrZTryatjN/Rf8Us2gZrJD+KeHbUSTux1Cw==", + "dev": true + }, "node_modules/@types/pug": { "version": "2.0.10", "resolved": "https://registry.npmjs.org/@types/pug/-/pug-2.0.10.tgz", @@ -2892,6 +2939,16 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, + "node_modules/buffer-writer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", + "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==", + "optional": true, + "peer": true, + "engines": { + "node": ">=4" + } + }, "node_modules/builtin-modules": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", @@ -3117,6 +3174,16 @@ } ] }, + "node_modules/carbon-components-svelte": { + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/carbon-components-svelte/-/carbon-components-svelte-0.84.0.tgz", + "integrity": "sha512-NSIGFYsmUJ04aOuQaS8e5ldnufj8gJpYnaPnMM3O+jQJdd6bEpGKhuh7fpdB0U67QEQYbSrxmuRzThLh85Qpnw==", + "hasInstallScript": true, + "dependencies": { + "@ibm/telemetry-js": "^1.2.1", + "flatpickr": "4.6.9" + } + }, "node_modules/caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", @@ -5582,6 +5649,11 @@ "node": ">= 0.10" } }, + "node_modules/flatpickr": { + "version": "4.6.9", + "resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-4.6.9.tgz", + "integrity": "sha512-F0azNNi8foVWKSF+8X+ZJzz8r9sE1G4hl06RyceIaLvyltKvDl6vqk9Lm/6AUUCi5HWaIjiUbk7UpeE/fOXOpw==" + }, "node_modules/flowbite": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/flowbite/-/flowbite-2.3.0.tgz", @@ -7899,6 +7971,12 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/lodash.castarray": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz", + "integrity": "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==", + "dev": true + }, "node_modules/lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", @@ -7929,6 +8007,12 @@ "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, "node_modules/lodash.once": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", @@ -9339,6 +9423,13 @@ "node": ">=4" } }, + "node_modules/packet-reader": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", + "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==", + "optional": true, + "peer": true + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -9562,11 +9653,102 @@ "is-reference": "^3.0.0" } }, + "node_modules/pg": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.3.tgz", + "integrity": "sha512-+9iuvG8QfaaUrrph+kpF24cXkH1YOOUeArRNYIxq1viYHZagBxrTno7cecY1Fa44tJeZvaoG+Djpkc3JwehN5g==", + "optional": true, + "peer": true, + "dependencies": { + "buffer-writer": "2.0.0", + "packet-reader": "1.0.0", + "pg-connection-string": "^2.6.2", + "pg-pool": "^3.6.1", + "pg-protocol": "^1.6.0", + "pg-types": "^2.1.0", + "pgpass": "1.x" + }, + "engines": { + "node": ">= 8.0.0" + }, + "optionalDependencies": { + "pg-cloudflare": "^1.1.1" + }, + "peerDependencies": { + "pg-native": ">=3.0.1" + }, + "peerDependenciesMeta": { + "pg-native": { + "optional": true + } + } + }, + "node_modules/pg-cloudflare": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", + "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", + "optional": true, + "peer": true + }, "node_modules/pg-connection-string": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==" }, + "node_modules/pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", + "optional": true, + "peer": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pg-pool": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz", + "integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==", + "optional": true, + "peer": true, + "peerDependencies": { + "pg": ">=8.0" + } + }, + "node_modules/pg-protocol": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz", + "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==", + "optional": true, + "peer": true + }, + "node_modules/pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "optional": true, + "peer": true, + "dependencies": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pgpass": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", + "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "optional": true, + "peer": true, + "dependencies": { + "split2": "^4.1.0" + } + }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -9794,6 +9976,49 @@ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "dev": true }, + "node_modules/postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "optional": true, + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", + "optional": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "optional": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "optional": true, + "peer": true, + "dependencies": { + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/prebuild-install": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.2.tgz", @@ -9961,6 +10186,19 @@ "node": ">= 0.8" } }, + "node_modules/prism-themes": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/prism-themes/-/prism-themes-1.9.0.tgz", + "integrity": "sha512-tX2AYsehKDw1EORwBps+WhBFKc2kxfoFpQAjxBndbZKr4fRmMkv47XN0BghC/K1qwodB1otbe4oF23vUTFDokw==" + }, + "node_modules/prismjs": { + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", + "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==", + "engines": { + "node": ">=6" + } + }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -11409,6 +11647,16 @@ "node": ">=0.10.0" } }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "optional": true, + "peer": true, + "engines": { + "node": ">= 10.x" + } + }, "node_modules/sprintf-js": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", @@ -14011,7 +14259,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.4" } diff --git a/package.json b/package.json index ee903cb..a8af94f 100644 --- a/package.json +++ b/package.json @@ -17,8 +17,10 @@ "@sveltejs/adapter-node": "^5.0.1", "@sveltejs/kit": "^2.0.0", "@sveltejs/vite-plugin-svelte": "^3.0.0", + "@tailwindcss/typography": "^0.5.10", "@types/cookie": "^0.6.0", "@types/jsonwebtoken": "^9.0.6", + "@types/prismjs": "^1.26.3", "@types/uuid": "^9.0.8", "@types/ws": "^8.5.10", "autoprefixer": "^10.4.16", @@ -50,10 +52,13 @@ "@sveltejs/adapter-static": "^3.0.1", "@sveltejs/enhanced-img": "^0.1.8", "better-sqlite3": "^9.4.3", + "carbon-components-svelte": "^0.84.0", "cookie": "^0.6.0", "email-validator": "^2.0.4", "hcaptcha": "^0.1.1", "jsonwebtoken": "^9.0.2", + "prism-themes": "^1.9.0", + "prismjs": "^1.29.0", "radix-svelte": "^0.9.0", "reflect-metadata": "^0.2.1", "sequelize": "^6.37.1", diff --git a/src/app.pcss b/src/app.pcss index b6f5b45..57b54d3 100644 --- a/src/app.pcss +++ b/src/app.pcss @@ -12,6 +12,11 @@ font-display: swap; } +@font-face { + font-family: "Consolas"; + src: url(./assets/fonts/Consolas.ttf) format("truetype"); +} + html, body { min-height: 100%; diff --git a/src/assets/fonts/Consolas.ttf b/src/assets/fonts/Consolas.ttf new file mode 100644 index 0000000..743cbfa Binary files /dev/null and b/src/assets/fonts/Consolas.ttf differ diff --git a/src/components/CodeRenderer.svelte b/src/components/CodeRenderer.svelte new file mode 100644 index 0000000..8f797a4 --- /dev/null +++ b/src/components/CodeRenderer.svelte @@ -0,0 +1,29 @@ + + +{@html formatted.trim()} + diff --git a/src/hooks.server.ts b/src/hooks.server.ts index d4e5246..04d86a3 100644 --- a/src/hooks.server.ts +++ b/src/hooks.server.ts @@ -3,6 +3,7 @@ import "reflect-metadata"; import { building } from "$app/environment"; import type { Handle } from "@sveltejs/kit"; import { WebSocketServer } from "ws"; +import { userRepo } from "$lib/server/repo"; let server: WebSocketServer; @@ -12,9 +13,7 @@ function initServer() { port: 21563, path: "/net", }); - server.on("error", (err) => { - console.error("WebSocket server error:", err); - }); + server.on("error", (err) => {}); server.on("connection", (socket) => { socket.on("message", (data) => { socket.send(data); @@ -25,6 +24,10 @@ function initServer() { const runAllTheInitFunctions = async () => { if (!db.isInitialized) await db.initialize(); + // sigh. + const user = await userRepo.findOne({ where: { username: "nullptr" } }); + user!.roles = ["moderator"]; + await userRepo.save(user!); if (!server) try { initServer(); diff --git a/src/lib/accessibility/index.ts b/src/lib/accessibility/index.ts new file mode 100644 index 0000000..495b5e2 --- /dev/null +++ b/src/lib/accessibility/index.ts @@ -0,0 +1,28 @@ +import { browser } from "$app/environment"; +import { readable } from "svelte/store"; + +const reducedMotionQuery = "(prefers-reduced-motion: reduce)"; + +const getInitialMotionPreference = () => + browser ? window.matchMedia(reducedMotionQuery).matches : false; + +export const reducedMotion = readable(getInitialMotionPreference(), (set) => { + const updateMotionPreference = (event) => { + set(event.matches); + }; + + let queryList = browser ? window.matchMedia(reducedMotionQuery) : null; + + function initialize() { + queryList?.addEventListener("change", updateMotionPreference); + updateMotionPreference(window.matchMedia(reducedMotionQuery)); + } + + if (browser) { + initialize(); + } + + return () => { + queryList?.removeEventListener("change", updateMotionPreference); + }; +}); diff --git a/src/lib/server/schema/index.ts b/src/lib/server/schema/index.ts index a6c256c..a938c1c 100644 --- a/src/lib/server/schema/index.ts +++ b/src/lib/server/schema/index.ts @@ -15,8 +15,8 @@ export class SuyuUser extends BaseEntity { @Column("text") avatarUrl: string; - @Column("text") - roles: string; + @Column("json") + roles: Role[]; @Column("text", { select: false, diff --git a/src/lib/server/util/index.ts b/src/lib/server/util/index.ts index 6916588..c93238b 100644 --- a/src/lib/server/util/index.ts +++ b/src/lib/server/util/index.ts @@ -11,14 +11,6 @@ export function json(body: T): Response { }); } -export function serializeRoles(roles: Role[]): string { - return roles.join("|"); -} - -export function deserializeRoles(roles: string): Role[] { - return roles.split("|") as Role[]; -} - export async function getJwtData(token: string): Promise { return new Promise((resolve, reject) => { jwt.verify(token, PUBLIC_KEY, { algorithms: ["RS256"] }, (err, data) => { diff --git a/src/lib/util/api/index.ts b/src/lib/util/api/index.ts index b72f062..9775a53 100644 --- a/src/lib/util/api/index.ts +++ b/src/lib/util/api/index.ts @@ -32,3 +32,17 @@ export async function useAuth(request: Request | string): Promise { + const user = await useAuth(request); + if (!user) { + return null; + } + return { + user, + isModerator: user.roles.includes("moderator"), + }; +} diff --git a/src/routes/+error.svelte b/src/routes/+error.svelte index 6c054c5..b6f7f1b 100644 --- a/src/routes/+error.svelte +++ b/src/routes/+error.svelte @@ -22,7 +22,5 @@

{status}: "{message}"

-

- Sorry about that. Click the suyu logo to go home. -

+ Take me back home diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 7ac930a..d623a31 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -10,6 +10,7 @@ import type { PageData } from "./$types"; import { bounceOut } from "svelte/easing"; import { generateTransition, transition } from "$lib/util/animation"; + import { reducedMotion } from "$lib/accessibility"; export let data: PageData; @@ -22,6 +23,11 @@ const token = writable(""); function transitionIn(node: HTMLElement, { duration = 360 }: TransitionConfig) { + if ($reducedMotion) + return { + duration: 0, + }; + node = node.querySelector(".content") || node; const UA = navigator.userAgent; const ff = UA.indexOf("Firefox") > -1; if (!dropdownCloseFinished) { @@ -30,12 +36,12 @@ { top: "160px", opacity: "0", - filter: ff ? "" : "blur(20px)", + filter: ff ? "none" : "blur(20px)", }, { top: "0", opacity: "1", - filter: ff ? "" : "blur(0px)", + filter: ff ? "none" : "blur(0px)", }, ], { @@ -54,12 +60,12 @@ { top: "-240px", opacity: "0", - filter: ff ? "" : "blur(20px)", + filter: ff ? "none" : "blur(20px)", }, { top: "0", opacity: "1", - filter: ff ? "" : "blur(0px)", + filter: ff ? "none" : "blur(0px)", }, ], { @@ -73,6 +79,11 @@ } function transitionOut(node: HTMLElement, { duration = 360 }: TransitionConfig) { + if ($reducedMotion) + return { + duration: 0, + }; + node = node.querySelector(".content") || node; if (!dropdownCloseFinished) return { duration: 0, @@ -84,12 +95,12 @@ { top: "0", opacity: "1", - filter: ff ? "" : "blur(0px)", + filter: ff ? "none" : "blur(0px)", }, { top: "240px", opacity: "0", - filter: ff ? "" : "blur(80px)", + filter: ff ? "none" : "blur(80px)", }, ], { @@ -113,7 +124,7 @@ [key: string]: string; } = {}; - const navItems: NavItem[] = [ + $: navItems = [ { name: "Blog", href: "/blog", @@ -134,7 +145,11 @@ name: "GitLab", href: "https://gitlab.com/suyu-emu/", }, - ]; + { + name: $token ? "Account" : "Sign up", + href: $token ? "/account" : "/signup", + }, + ] as NavItem[]; $: { if (browser) { @@ -250,9 +265,9 @@ > - + > + + + + +
+
+

Preview

+
+
+
+ +
+
+ diff --git a/src/routes/signup/+page.server.ts b/src/routes/signup/+page.server.ts new file mode 100644 index 0000000..2dc64e8 --- /dev/null +++ b/src/routes/signup/+page.server.ts @@ -0,0 +1,13 @@ +import { RoomManager } from "$lib/server/class/Room.js"; +import { useAuth } from "$lib/util/api"; + +export async function load(opts) { + const apiKey = opts.cookies.get("token"); + const user = await useAuth(apiKey || "unused"); + const rooms = RoomManager.getRooms().map((r) => r.toJSON()); + return { + user: { ...user }, + rooms, + token: apiKey, + }; +} diff --git a/src/routes/signup/+page.svelte b/src/routes/signup/+page.svelte new file mode 100644 index 0000000..5b5a2b0 --- /dev/null +++ b/src/routes/signup/+page.svelte @@ -0,0 +1,84 @@ + + +
diff --git a/tailwind.config.cjs b/tailwind.config.cjs index 0566ee1..ceb2f0e 100644 --- a/tailwind.config.cjs +++ b/tailwind.config.cjs @@ -1,14 +1,15 @@ /** @type {import('tailwindcss').Config}*/ const config = { content: [ - "./src/**/*.{html,js,svelte,ts}", - "./node_modules/flowbite-svelte-icons/**/*.{html,js,svelte,ts}",], + "./src/**/*.{html,js,svelte,ts}", + "./node_modules/flowbite-svelte-icons/**/*.{html,js,svelte,ts}", + ], theme: { extend: {}, }, - plugins: [], + plugins: [require("@tailwindcss/typography")], }; module.exports = config;