diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..520b89d --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +**/.DS_Store +node_modules/ +dist/ diff --git a/index.html b/index.html new file mode 100644 index 0000000..f4976ad --- /dev/null +++ b/index.html @@ -0,0 +1,13 @@ + + + + + + + space social + + +
+ + + diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..cc6d2a5 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1185 @@ +{ + "name": "spacesocial-client", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "spacesocial-client", + "version": "1.0.0", + "license": "ISC", + "devDependencies": { + "@sveltejs/vite-plugin-svelte": "^3.1.1", + "svelte": "^4.2.18", + "vite": "^5.3.1" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz", + "integrity": "sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.0.tgz", + "integrity": "sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz", + "integrity": "sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.0.tgz", + "integrity": "sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.0.tgz", + "integrity": "sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.0.tgz", + "integrity": "sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz", + "integrity": "sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.0.tgz", + "integrity": "sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.0.tgz", + "integrity": "sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.0.tgz", + "integrity": "sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.0.tgz", + "integrity": "sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz", + "integrity": "sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz", + "integrity": "sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.0.tgz", + "integrity": "sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.0.tgz", + "integrity": "sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz", + "integrity": "sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@sveltejs/vite-plugin-svelte": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-3.1.1.tgz", + "integrity": "sha512-rimpFEAboBBHIlzISibg94iP09k/KYdHgVhJlcsTfn7KMBhc70jFX/GRWkRdFCc2fdnk+4+Bdfej23cMDnJS6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sveltejs/vite-plugin-svelte-inspector": "^2.1.0", + "debug": "^4.3.4", + "deepmerge": "^4.3.1", + "kleur": "^4.1.5", + "magic-string": "^0.30.10", + "svelte-hmr": "^0.16.0", + "vitefu": "^0.2.5" + }, + "engines": { + "node": "^18.0.0 || >=20" + }, + "peerDependencies": { + "svelte": "^4.0.0 || ^5.0.0-next.0", + "vite": "^5.0.0" + } + }, + "node_modules/@sveltejs/vite-plugin-svelte-inspector": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte-inspector/-/vite-plugin-svelte-inspector-2.1.0.tgz", + "integrity": "sha512-9QX28IymvBlSCqsCll5t0kQVxipsfhFFL+L2t3nTWfXnddYwxBuAEtTtlaVQpRz9c37BhJjltSeY4AJSC03SSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.0.0 || >=20" + }, + "peerDependencies": { + "@sveltejs/vite-plugin-svelte": "^3.0.0", + "svelte": "^4.0.0 || ^5.0.0-next.0", + "vite": "^5.0.0" + } + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true, + "license": "MIT" + }, + "node_modules/acorn": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz", + "integrity": "sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/axobject-query": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.0.0.tgz", + "integrity": "sha512-+60uv1hiVFhHZeO+Lz0RYzsVHy5Wr1ayX0mwda9KPDVLNJgZ1T9Ny7VmFbLDzxsH0D87I86vgj3gFrjTJUYznw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/code-red": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/code-red/-/code-red-1.0.4.tgz", + "integrity": "sha512-7qJWqItLA8/VPVlKJlFXU+NBlo/qyfs39aJcuMT/2ere32ZqvF5OSxgdM5xOfJJ7O429gg2HM47y8v9P+9wrNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15", + "@types/estree": "^1.0.1", + "acorn": "^8.10.0", + "estree-walker": "^3.0.3", + "periscopic": "^3.1.0" + } + }, + "node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/is-reference": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.2.tgz", + "integrity": "sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/locate-character": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz", + "integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==", + "dev": true, + "license": "MIT" + }, + "node_modules/magic-string": { + "version": "0.30.10", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", + "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + } + }, + "node_modules/mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/periscopic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/periscopic/-/periscopic-3.1.0.tgz", + "integrity": "sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^3.0.0", + "is-reference": "^3.0.0" + } + }, + "node_modules/picocolors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", + "dev": true, + "license": "ISC" + }, + "node_modules/postcss": { + "version": "8.4.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", + "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/rollup": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.0.tgz", + "integrity": "sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.5" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.18.0", + "@rollup/rollup-android-arm64": "4.18.0", + "@rollup/rollup-darwin-arm64": "4.18.0", + "@rollup/rollup-darwin-x64": "4.18.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.18.0", + "@rollup/rollup-linux-arm-musleabihf": "4.18.0", + "@rollup/rollup-linux-arm64-gnu": "4.18.0", + "@rollup/rollup-linux-arm64-musl": "4.18.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.18.0", + "@rollup/rollup-linux-riscv64-gnu": "4.18.0", + "@rollup/rollup-linux-s390x-gnu": "4.18.0", + "@rollup/rollup-linux-x64-gnu": "4.18.0", + "@rollup/rollup-linux-x64-musl": "4.18.0", + "@rollup/rollup-win32-arm64-msvc": "4.18.0", + "@rollup/rollup-win32-ia32-msvc": "4.18.0", + "@rollup/rollup-win32-x64-msvc": "4.18.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/source-map-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/svelte": { + "version": "4.2.18", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-4.2.18.tgz", + "integrity": "sha512-d0FdzYIiAePqRJEb90WlJDkjUEx42xhivxN8muUBmfZnP+tzUgz12DJ2hRJi8sIHCME7jeK1PTMgKPSfTd8JrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.2.1", + "@jridgewell/sourcemap-codec": "^1.4.15", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/estree": "^1.0.1", + "acorn": "^8.9.0", + "aria-query": "^5.3.0", + "axobject-query": "^4.0.0", + "code-red": "^1.0.3", + "css-tree": "^2.3.1", + "estree-walker": "^3.0.3", + "is-reference": "^3.0.1", + "locate-character": "^3.0.0", + "magic-string": "^0.30.4", + "periscopic": "^3.1.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/svelte-hmr": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.16.0.tgz", + "integrity": "sha512-Gyc7cOS3VJzLlfj7wKS0ZnzDVdv3Pn2IuVeJPk9m2skfhcu5bq3wtIZyQGggr7/Iim5rH5cncyQft/kRLupcnA==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^12.20 || ^14.13.1 || >= 16" + }, + "peerDependencies": { + "svelte": "^3.19.0 || ^4.0.0" + } + }, + "node_modules/vite": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.3.1.tgz", + "integrity": "sha512-XBmSKRLXLxiaPYamLv3/hnP/KXDai1NDexN0FpkTaZXTfycHvkRHoenpgl/fvuK/kPbB6xAgoyiryAhQNxYmAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.38", + "rollup": "^4.13.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vitefu": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-0.2.5.tgz", + "integrity": "sha512-SgHtMLoqaeeGnd2evZ849ZbACbnwQCIwRH57t18FxcXoZop0uQu0uzlIhJBlF/eWVzuce0sHeqPcDo+evVcg8Q==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "vite": "^3.0.0 || ^4.0.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "vite": { + "optional": true + } + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..273a38d --- /dev/null +++ b/package.json @@ -0,0 +1,18 @@ +{ + "name": "spacesocial-client", + "version": "0.1.0", + "description": "social media for the galaxy-wide-web! 🌌", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "author": "", + "license": "ISC", + "devDependencies": { + "@sveltejs/vite-plugin-svelte": "^3.1.1", + "svelte": "^4.2.18", + "vite": "^5.3.1" + } +} diff --git a/public/avatar/ari.jpg b/public/avatar/ari.jpg deleted file mode 100644 index 1be0b83..0000000 Binary files a/public/avatar/ari.jpg and /dev/null differ diff --git a/public/css/style.css b/public/css/style.css deleted file mode 100644 index 10b34f5..0000000 --- a/public/css/style.css +++ /dev/null @@ -1,240 +0,0 @@ -:root { - --fg0: #eee; - --bg0: #080808; - --bg1: #101010; - --bg2: #121212; - --accent: #b7fd49; -} - -body { - margin: 0; - padding: 0; - - background-color: var(--bg0); - color: var(--fg0); - - font-family: "Inter", sans-serif; -} - -#feed { - width: 720px; - margin: 0 auto; - background-color: var(--bg1); -} - -.post-container { - padding: 20px 32px; - border-bottom: 1px solid #8884; - transition: background-color .1s; -} - -.post-container:hover { - background-color: var(--bg2); -} - -.post-context { - margin-bottom: 8px; - padding-left: 58px; - display: flex; - flex-direction: row; - align-items: center; - color: var(--accent); - opacity: .8; - transition: opacity .1s; -} - -.post-container:hover .post-context { - opacity: 1; -} - -.post-context-icon { - margin-right: 4px; -} - -.post-context a, -.post-context a:visited, -.post-header-container a, -.post-header-container a:visited { - color: inherit; - text-decoration: none; -} -.post-context a:hover, -.post-header-container a:hover { - text-decoration: underline; -} - -.post-context-time { - margin-left: auto; -} - -article.post { /* ... */ } - -.post-header-container { - display: flex; - flex-direction: row; -} - -.post-avatar-container { - margin-right: 12px; -} - -.post-avatar { - border-radius: 8px; - box-shadow: 2px 2px #0004; - /* transition: transform .2s ease-out; */ -} - -/* .post-avatar:hover { */ -/* transform: scale(1.1); */ -/* } */ - -.post-header { - display: flex; - flex-grow: 1; - flex-direction: row; -} - -.post-info { - margin-left: auto; -} - -.post-user-info a { - display: block; -} - -.post-body { - margin-top: 8px; -} - -.post-media-container { - margin-top: 8px; - display: grid; - grid-gap: 8px; -} - -.post-media-container[data-count="1"] { - grid-template-rows: 1fr; -} - -.post-media-container[data-count="2"] { - grid-template-columns: 1fr 1fr; - grid-template-rows: 1fr; -} - -.post-media-container[data-count="3"] { - grid-template-columns: 1fr .5fr; - grid-template-rows: 1fr 1fr; -} - -.post-media-container[data-count="4"] { - grid-template-columns: 1fr 1fr; - grid-template-rows: 1fr 1fr; -} - -.post-media { - border-radius: 12px; - background-color: #000; - overflow: hidden; -} - -.post-media a { - width: 100%; - height: 100%; - display: block; - cursor: zoom-in; -} - -.post-media a img { - width: 100%; - height: 100%; - display: block; - object-fit: contain; -} - -.post-media-container > :nth-child(1) { - grid-column: 1/2; - grid-row: 1/2; -} - -.post-media-container[data-count="3"] > :nth-child(1) { - grid-row: 1/3; -} - -.post-media-container > :nth-child(2) { - grid-column: 2/2; - grid-row: 1/2; -} - -.post-media-container > :nth-child(3) { - grid-column: 1/2; - grid-row: 2/2; -} - -.post-media-container[data-count="3"] > :nth-child(3) { - grid-column: 2/2; - grid-row: 2/2; -} - -.post-media-container > :nth-child(4) { - grid-column: 2/2; - grid-row: 2/2; -} - -.post-container footer { - opacity: .8; - transition: opacity .1s; -} - -.post-container:hover footer { - opacity: 1; -} - -.post-reactions { - margin-top: 8px; -} - -button.reaction { - padding: 6px 8px; - font-size: 1em; - background: none; - color: inherit; - border: none; - border-radius: 8px; - /* transition: transform .1s ease-out; */ -} - -button.reaction:hover, -.post-actions button:hover { - /* transform: scale(1.1); */ - background: #8881; -} - -button.reaction:active, -.post-actions button:active { - /* transform: scale(.95); */ - background: #0001; -} - -button.reaction.active, -.post-actions button.active { - background: var(--accent); - color: var(--bg0); -} - -.post-actions { - margin-top: 8px; -} - -.post-actions button { - padding: 6px 8px; - font-size: 1em; - background: none; - color: inherit; - border: none; - border-radius: 8px; - transition: transform .1s ease-out; -} - -.post-actions button .count { - opacity: .5; -} diff --git a/public/font/inter/Inter-Black.woff2 b/public/font/inter/Inter-Black.woff2 new file mode 100644 index 0000000..18b35db Binary files /dev/null and b/public/font/inter/Inter-Black.woff2 differ diff --git a/public/font/inter/Inter-BlackItalic.woff2 b/public/font/inter/Inter-BlackItalic.woff2 new file mode 100644 index 0000000..02c9d8e Binary files /dev/null and b/public/font/inter/Inter-BlackItalic.woff2 differ diff --git a/public/font/inter/Inter-Bold.woff2 b/public/font/inter/Inter-Bold.woff2 new file mode 100644 index 0000000..0f1b157 Binary files /dev/null and b/public/font/inter/Inter-Bold.woff2 differ diff --git a/public/font/inter/Inter-BoldItalic.woff2 b/public/font/inter/Inter-BoldItalic.woff2 new file mode 100644 index 0000000..bc50f24 Binary files /dev/null and b/public/font/inter/Inter-BoldItalic.woff2 differ diff --git a/public/font/inter/Inter-ExtraBold.woff2 b/public/font/inter/Inter-ExtraBold.woff2 new file mode 100644 index 0000000..b113368 Binary files /dev/null and b/public/font/inter/Inter-ExtraBold.woff2 differ diff --git a/public/font/inter/Inter-ExtraBoldItalic.woff2 b/public/font/inter/Inter-ExtraBoldItalic.woff2 new file mode 100644 index 0000000..a5b76ca Binary files /dev/null and b/public/font/inter/Inter-ExtraBoldItalic.woff2 differ diff --git a/public/font/inter/Inter-ExtraLight.woff2 b/public/font/inter/Inter-ExtraLight.woff2 new file mode 100644 index 0000000..1d77ae8 Binary files /dev/null and b/public/font/inter/Inter-ExtraLight.woff2 differ diff --git a/public/font/inter/Inter-ExtraLightItalic.woff2 b/public/font/inter/Inter-ExtraLightItalic.woff2 new file mode 100644 index 0000000..8c68492 Binary files /dev/null and b/public/font/inter/Inter-ExtraLightItalic.woff2 differ diff --git a/public/font/inter/Inter-Italic.woff2 b/public/font/inter/Inter-Italic.woff2 new file mode 100644 index 0000000..4c24ce2 Binary files /dev/null and b/public/font/inter/Inter-Italic.woff2 differ diff --git a/public/font/inter/Inter-Light.woff2 b/public/font/inter/Inter-Light.woff2 new file mode 100644 index 0000000..dbe6143 Binary files /dev/null and b/public/font/inter/Inter-Light.woff2 differ diff --git a/public/font/inter/Inter-LightItalic.woff2 b/public/font/inter/Inter-LightItalic.woff2 new file mode 100644 index 0000000..a40d042 Binary files /dev/null and b/public/font/inter/Inter-LightItalic.woff2 differ diff --git a/public/font/inter/Inter-Medium.woff2 b/public/font/inter/Inter-Medium.woff2 new file mode 100644 index 0000000..0fd2ee7 Binary files /dev/null and b/public/font/inter/Inter-Medium.woff2 differ diff --git a/public/font/inter/Inter-MediumItalic.woff2 b/public/font/inter/Inter-MediumItalic.woff2 new file mode 100644 index 0000000..9676715 Binary files /dev/null and b/public/font/inter/Inter-MediumItalic.woff2 differ diff --git a/public/font/inter/Inter-Regular.woff2 b/public/font/inter/Inter-Regular.woff2 new file mode 100644 index 0000000..b8699af Binary files /dev/null and b/public/font/inter/Inter-Regular.woff2 differ diff --git a/public/font/inter/Inter-SemiBold.woff2 b/public/font/inter/Inter-SemiBold.woff2 new file mode 100644 index 0000000..95c48b1 Binary files /dev/null and b/public/font/inter/Inter-SemiBold.woff2 differ diff --git a/public/font/inter/Inter-SemiBoldItalic.woff2 b/public/font/inter/Inter-SemiBoldItalic.woff2 new file mode 100644 index 0000000..ddfe19e Binary files /dev/null and b/public/font/inter/Inter-SemiBoldItalic.woff2 differ diff --git a/public/font/inter/Inter-Thin.woff2 b/public/font/inter/Inter-Thin.woff2 new file mode 100644 index 0000000..0790960 Binary files /dev/null and b/public/font/inter/Inter-Thin.woff2 differ diff --git a/public/font/inter/Inter-ThinItalic.woff2 b/public/font/inter/Inter-ThinItalic.woff2 new file mode 100644 index 0000000..a7bf213 Binary files /dev/null and b/public/font/inter/Inter-ThinItalic.woff2 differ diff --git a/public/font/inter/InterDisplay-Black.woff2 b/public/font/inter/InterDisplay-Black.woff2 new file mode 100644 index 0000000..8138123 Binary files /dev/null and b/public/font/inter/InterDisplay-Black.woff2 differ diff --git a/public/font/inter/InterDisplay-BlackItalic.woff2 b/public/font/inter/InterDisplay-BlackItalic.woff2 new file mode 100644 index 0000000..735ba21 Binary files /dev/null and b/public/font/inter/InterDisplay-BlackItalic.woff2 differ diff --git a/public/font/inter/InterDisplay-Bold.woff2 b/public/font/inter/InterDisplay-Bold.woff2 new file mode 100644 index 0000000..11c6719 Binary files /dev/null and b/public/font/inter/InterDisplay-Bold.woff2 differ diff --git a/public/font/inter/InterDisplay-BoldItalic.woff2 b/public/font/inter/InterDisplay-BoldItalic.woff2 new file mode 100644 index 0000000..5b6a1fb Binary files /dev/null and b/public/font/inter/InterDisplay-BoldItalic.woff2 differ diff --git a/public/font/inter/InterDisplay-ExtraBold.woff2 b/public/font/inter/InterDisplay-ExtraBold.woff2 new file mode 100644 index 0000000..9058e98 Binary files /dev/null and b/public/font/inter/InterDisplay-ExtraBold.woff2 differ diff --git a/public/font/inter/InterDisplay-ExtraBoldItalic.woff2 b/public/font/inter/InterDisplay-ExtraBoldItalic.woff2 new file mode 100644 index 0000000..4cd61c0 Binary files /dev/null and b/public/font/inter/InterDisplay-ExtraBoldItalic.woff2 differ diff --git a/public/font/inter/InterDisplay-ExtraLight.woff2 b/public/font/inter/InterDisplay-ExtraLight.woff2 new file mode 100644 index 0000000..8621b29 Binary files /dev/null and b/public/font/inter/InterDisplay-ExtraLight.woff2 differ diff --git a/public/font/inter/InterDisplay-ExtraLightItalic.woff2 b/public/font/inter/InterDisplay-ExtraLightItalic.woff2 new file mode 100644 index 0000000..689c8d9 Binary files /dev/null and b/public/font/inter/InterDisplay-ExtraLightItalic.woff2 differ diff --git a/public/font/inter/InterDisplay-Italic.woff2 b/public/font/inter/InterDisplay-Italic.woff2 new file mode 100644 index 0000000..11f20bc Binary files /dev/null and b/public/font/inter/InterDisplay-Italic.woff2 differ diff --git a/public/font/inter/InterDisplay-Light.woff2 b/public/font/inter/InterDisplay-Light.woff2 new file mode 100644 index 0000000..446301c Binary files /dev/null and b/public/font/inter/InterDisplay-Light.woff2 differ diff --git a/public/font/inter/InterDisplay-LightItalic.woff2 b/public/font/inter/InterDisplay-LightItalic.woff2 new file mode 100644 index 0000000..f688196 Binary files /dev/null and b/public/font/inter/InterDisplay-LightItalic.woff2 differ diff --git a/public/font/inter/InterDisplay-Medium.woff2 b/public/font/inter/InterDisplay-Medium.woff2 new file mode 100644 index 0000000..29160b2 Binary files /dev/null and b/public/font/inter/InterDisplay-Medium.woff2 differ diff --git a/public/font/inter/InterDisplay-MediumItalic.woff2 b/public/font/inter/InterDisplay-MediumItalic.woff2 new file mode 100644 index 0000000..ef1bcbe Binary files /dev/null and b/public/font/inter/InterDisplay-MediumItalic.woff2 differ diff --git a/public/font/inter/InterDisplay-Regular.woff2 b/public/font/inter/InterDisplay-Regular.woff2 new file mode 100644 index 0000000..a6c04f6 Binary files /dev/null and b/public/font/inter/InterDisplay-Regular.woff2 differ diff --git a/public/font/inter/InterDisplay-SemiBold.woff2 b/public/font/inter/InterDisplay-SemiBold.woff2 new file mode 100644 index 0000000..2b4db23 Binary files /dev/null and b/public/font/inter/InterDisplay-SemiBold.woff2 differ diff --git a/public/font/inter/InterDisplay-SemiBoldItalic.woff2 b/public/font/inter/InterDisplay-SemiBoldItalic.woff2 new file mode 100644 index 0000000..59091db Binary files /dev/null and b/public/font/inter/InterDisplay-SemiBoldItalic.woff2 differ diff --git a/public/font/inter/InterDisplay-Thin.woff2 b/public/font/inter/InterDisplay-Thin.woff2 new file mode 100644 index 0000000..dc0b948 Binary files /dev/null and b/public/font/inter/InterDisplay-Thin.woff2 differ diff --git a/public/font/inter/InterDisplay-ThinItalic.woff2 b/public/font/inter/InterDisplay-ThinItalic.woff2 new file mode 100644 index 0000000..96439c0 Binary files /dev/null and b/public/font/inter/InterDisplay-ThinItalic.woff2 differ diff --git a/public/font/inter/InterVariable-Italic.woff2 b/public/font/inter/InterVariable-Italic.woff2 new file mode 100644 index 0000000..f22ec25 Binary files /dev/null and b/public/font/inter/InterVariable-Italic.woff2 differ diff --git a/public/font/inter/InterVariable.woff2 b/public/font/inter/InterVariable.woff2 new file mode 100644 index 0000000..22a12b0 Binary files /dev/null and b/public/font/inter/InterVariable.woff2 differ diff --git a/public/font/inter/LICENSE.txt b/public/font/inter/LICENSE.txt new file mode 100644 index 0000000..9b2ca37 --- /dev/null +++ b/public/font/inter/LICENSE.txt @@ -0,0 +1,92 @@ +Copyright (c) 2016 The Inter Project Authors (https://github.com/rsms/inter) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION AND CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/public/font/inter/inter.css b/public/font/inter/inter.css new file mode 100644 index 0000000..413e197 --- /dev/null +++ b/public/font/inter/inter.css @@ -0,0 +1,57 @@ +/* Variable fonts usage: +:root { font-family: "Inter", sans-serif; } +@supports (font-variation-settings: normal) { + :root { font-family: "InterVariable", sans-serif; font-optical-sizing: auto; } +} */ +@font-face { + font-family: InterVariable; + font-style: normal; + font-weight: 100 900; + font-display: swap; + src: url("InterVariable.woff2") format("woff2"); +} +@font-face { + font-family: InterVariable; + font-style: italic; + font-weight: 100 900; + font-display: swap; + src: url("InterVariable-Italic.woff2") format("woff2"); +} + +/* static fonts */ +@font-face { font-family: "Inter"; font-style: normal; font-weight: 100; font-display: swap; src: url("Inter-Thin.woff2") format("woff2"); } +@font-face { font-family: "Inter"; font-style: italic; font-weight: 100; font-display: swap; src: url("Inter-ThinItalic.woff2") format("woff2"); } +@font-face { font-family: "Inter"; font-style: normal; font-weight: 200; font-display: swap; src: url("Inter-ExtraLight.woff2") format("woff2"); } +@font-face { font-family: "Inter"; font-style: italic; font-weight: 200; font-display: swap; src: url("Inter-ExtraLightItalic.woff2") format("woff2"); } +@font-face { font-family: "Inter"; font-style: normal; font-weight: 300; font-display: swap; src: url("Inter-Light.woff2") format("woff2"); } +@font-face { font-family: "Inter"; font-style: italic; font-weight: 300; font-display: swap; src: url("Inter-LightItalic.woff2") format("woff2"); } +@font-face { font-family: "Inter"; font-style: normal; font-weight: 400; font-display: swap; src: url("Inter-Regular.woff2") format("woff2"); } +@font-face { font-family: "Inter"; font-style: italic; font-weight: 400; font-display: swap; src: url("Inter-Italic.woff2") format("woff2"); } +@font-face { font-family: "Inter"; font-style: normal; font-weight: 500; font-display: swap; src: url("Inter-Medium.woff2") format("woff2"); } +@font-face { font-family: "Inter"; font-style: italic; font-weight: 500; font-display: swap; src: url("Inter-MediumItalic.woff2") format("woff2"); } +@font-face { font-family: "Inter"; font-style: normal; font-weight: 600; font-display: swap; src: url("Inter-SemiBold.woff2") format("woff2"); } +@font-face { font-family: "Inter"; font-style: italic; font-weight: 600; font-display: swap; src: url("Inter-SemiBoldItalic.woff2") format("woff2"); } +@font-face { font-family: "Inter"; font-style: normal; font-weight: 700; font-display: swap; src: url("Inter-Bold.woff2") format("woff2"); } +@font-face { font-family: "Inter"; font-style: italic; font-weight: 700; font-display: swap; src: url("Inter-BoldItalic.woff2") format("woff2"); } +@font-face { font-family: "Inter"; font-style: normal; font-weight: 800; font-display: swap; src: url("Inter-ExtraBold.woff2") format("woff2"); } +@font-face { font-family: "Inter"; font-style: italic; font-weight: 800; font-display: swap; src: url("Inter-ExtraBoldItalic.woff2") format("woff2"); } +@font-face { font-family: "Inter"; font-style: normal; font-weight: 900; font-display: swap; src: url("Inter-Black.woff2") format("woff2"); } +@font-face { font-family: "Inter"; font-style: italic; font-weight: 900; font-display: swap; src: url("Inter-BlackItalic.woff2") format("woff2"); } +@font-face { font-family: "InterDisplay"; font-style: normal; font-weight: 100; font-display: swap; src: url("InterDisplay-Thin.woff2") format("woff2"); } +@font-face { font-family: "InterDisplay"; font-style: italic; font-weight: 100; font-display: swap; src: url("InterDisplay-ThinItalic.woff2") format("woff2"); } +@font-face { font-family: "InterDisplay"; font-style: normal; font-weight: 200; font-display: swap; src: url("InterDisplay-ExtraLight.woff2") format("woff2"); } +@font-face { font-family: "InterDisplay"; font-style: italic; font-weight: 200; font-display: swap; src: url("InterDisplay-ExtraLightItalic.woff2") format("woff2"); } +@font-face { font-family: "InterDisplay"; font-style: normal; font-weight: 300; font-display: swap; src: url("InterDisplay-Light.woff2") format("woff2"); } +@font-face { font-family: "InterDisplay"; font-style: italic; font-weight: 300; font-display: swap; src: url("InterDisplay-LightItalic.woff2") format("woff2"); } +@font-face { font-family: "InterDisplay"; font-style: normal; font-weight: 400; font-display: swap; src: url("InterDisplay-Regular.woff2") format("woff2"); } +@font-face { font-family: "InterDisplay"; font-style: italic; font-weight: 400; font-display: swap; src: url("InterDisplay-Italic.woff2") format("woff2"); } +@font-face { font-family: "InterDisplay"; font-style: normal; font-weight: 500; font-display: swap; src: url("InterDisplay-Medium.woff2") format("woff2"); } +@font-face { font-family: "InterDisplay"; font-style: italic; font-weight: 500; font-display: swap; src: url("InterDisplay-MediumItalic.woff2") format("woff2"); } +@font-face { font-family: "InterDisplay"; font-style: normal; font-weight: 600; font-display: swap; src: url("InterDisplay-SemiBold.woff2") format("woff2"); } +@font-face { font-family: "InterDisplay"; font-style: italic; font-weight: 600; font-display: swap; src: url("InterDisplay-SemiBoldItalic.woff2") format("woff2"); } +@font-face { font-family: "InterDisplay"; font-style: normal; font-weight: 700; font-display: swap; src: url("InterDisplay-Bold.woff2") format("woff2"); } +@font-face { font-family: "InterDisplay"; font-style: italic; font-weight: 700; font-display: swap; src: url("InterDisplay-BoldItalic.woff2") format("woff2"); } +@font-face { font-family: "InterDisplay"; font-style: normal; font-weight: 800; font-display: swap; src: url("InterDisplay-ExtraBold.woff2") format("woff2"); } +@font-face { font-family: "InterDisplay"; font-style: italic; font-weight: 800; font-display: swap; src: url("InterDisplay-ExtraBoldItalic.woff2") format("woff2"); } +@font-face { font-family: "InterDisplay"; font-style: normal; font-weight: 900; font-display: swap; src: url("InterDisplay-Black.woff2") format("woff2"); } +@font-face { font-family: "InterDisplay"; font-style: italic; font-weight: 900; font-display: swap; src: url("InterDisplay-BlackItalic.woff2") format("woff2"); } diff --git a/public/index.html b/public/index.html deleted file mode 100644 index 9ccfb02..0000000 --- a/public/index.html +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - - - - - - -
- -
-
-
- -
-
- - diff --git a/public/script/main.mjs b/public/script/main.mjs deleted file mode 100644 index 5fdda19..0000000 --- a/public/script/main.mjs +++ /dev/null @@ -1,302 +0,0 @@ -const aria_safe_regex = /([\u2700-\u27BF]|[\uE000-\uF8FF]|\uD83C[\uDC00-\uDFFF]|\uD83D[\uDC00-\uDFFF]|[\u2011-\u26FF]|\uD83E[\uDD10-\uDDFF]|[\r])/g; -const INSTANCE_URL = "soc.arimelody.me"; - -const sounds = { - "default": new Audio("sound/log.ogg"), - "post": new Audio("sound/success.ogg"), - "boost": new Audio("sound/hello.ogg"), -}; - -const actors = { - "@ari": { - "url": "https://soc.arimelody.me/@ari", - "name": "ari 💫", - "avatar": "avatar/ari.jpg", - } -}; - -const test_post = { - "context": { - "type": "boost", - "by": "@ari", - "at": 1718513838624, - }, - "author": "@ari", - "url": "/post/21c892b23701", - "at": 1718513988384, - "content": "hello world!~", - "media": [ - { "url": "media/ariyeah-button.png", "alt": "custom miiverse \"yeah!\" button" }, - { "url": "media/beer.jpg", "alt": "barney calhoun with beer" }, - { "url": "media/duck.jpg", "alt": "big rubber duck" }, - ], - "replies": 7, - "boosts": 13, - "reactions": [ - { "react": "⭐", "count": "52" }, - { "react": "❤️", "count": "9" }, - ], -}; - -const feed = document.getElementById("feed"); - -function render_post(data) { - // TODO: please god just use or make a library to build this - - const actor = actors[data.author]; - if (!actor) return; - const date = new Date(data.at); - - const post = document.createElement("article"); - post.classList.add("post-container"); - post.ariaLabel = actor.name.replace(aria_safe_regex, "").trim() + "; " + data.content + "; " + date.toLocaleTimeString(); - - if (data.context && data.context.by && actors[data.context.by]) { - // post context - const post_context = document.createElement("div"); - post_context.classList.add("post-context"); - - if (data.context.type == "boost") { - const post_context_icon = document.createElement("span"); - post_context_icon.classList.add("post-context-icon"); - post_context_icon.innerText = "🔁"; - post_context.appendChild(post_context_icon); - - const post_context_action = document.createElement("span"); - post_context_action.classList.add("post-context-action"); - const actor = actors[data.context.by]; - post_context_action.innerHTML = `boosted by ${actor.name}`; - post_context.appendChild(post_context_action); - - const post_context_time = document.createElement("span"); - post_context_time.classList.add("post-context-time"); - post_context_time.innerHTML = ``; - post_context.appendChild(post_context_time); - } - - post.appendChild(post_context); - } - - // the actual post - // article.post - const post_article = document.createElement("article"); - - const post_header_container = document.createElement("div"); - post_header_container.classList.add("post-header-container"); - const post_avatar_container = document.createElement("a"); - post_avatar_container.classList.add("post-avatar-container"); - post_avatar_container.href = actor.url; - const post_avatar = document.createElement("img"); - post_avatar.classList.add("post-avatar"); - post_avatar.src = actor.avatar; - post_avatar.alt = ""; - post_avatar.width = 48; - post_avatar.height = 48; - post_avatar.loading = "lazy"; - post_avatar.decoding = "async"; - post_avatar_container.appendChild(post_avatar); - post_header_container.appendChild(post_avatar_container); - - const post_header = document.createElement("header"); - post_header.classList.add("post-header"); - const post_user_info = document.createElement("div"); - post_user_info.classList.add("post-user-info"); - const post_user_info_name = document.createElement("a"); - post_user_info_name.classList.add("name"); - post_user_info_name.href = actor.url; - post_user_info_name.innerText = actor.name - post_user_info.appendChild(post_user_info_name); - const post_user_info_username = document.createElement("span"); - post_user_info_username.classList.add("username"); - post_user_info_username.href = actor.url; - post_user_info_username.innerText = data.author - post_user_info.appendChild(post_user_info_username); - post_header.appendChild(post_user_info); - const post_info = document.createElement("div"); - post_info.classList.add("post-info"); - const post_info_time = document.createElement("a"); - post_info_time.classList.add("created-at"); - const post_date = new Date(data.at); - post_info_time.innerHTML = ``; - post_info_time.href = post.url; - post_info.appendChild(post_info_time); - post_header.appendChild(post_info); - post_header_container.appendChild(post_header); - - post_article.appendChild(post_header_container); - - - const post_body = document.createElement("div"); - post_body.classList.add("post-body"); - - const post_content = document.createElement("span"); - post_content.classList.add("post-content"); - post_content.innerText = data.content; - post_body.appendChild(post_content); - - const media_container = document.createElement("div"); - media_container.classList.add("post-media-container"); - media_container.dataset.count = data.media.length; - data.media.forEach(media => { - const media_item = document.createElement("div"); - media_item.classList.add("post-media"); - const link = document.createElement("a"); - link.href = media.url; - const source = document.createElement("img"); - source.src = media.url; - source.alt = media.alt; - source.loading = "lazy"; - source.decoding = "async"; - link.appendChild(source); - media_item.appendChild(link); - media_container.appendChild(media_item); - }); - post_body.appendChild(media_container); - - post_article.appendChild(post_body); - - - const post_footer = document.createElement("footer"); - post_footer.classList.add("post-footer"); - - const post_reactions = document.createElement("div"); - post_reactions.classList.add("post-reactions"); - data.reactions.forEach(reaction => { - const btn = document.createElement("button"); - btn.classList.add("reaction"); - btn.type = "button"; - const emote = document.createElement("span"); - emote.innerText = reaction.react; - btn.appendChild(emote); - const count = document.createElement("span"); - count.classList.add("count"); - count.innerText = reaction.count; - btn.appendChild(count); - post_reactions.appendChild(btn); - }); - post_footer.appendChild(post_reactions); - - const post_actions = document.createElement("div"); - post_actions.classList.add("post-actions"); - - const reply_button = document.createElement("button"); - reply_button.type = "button"; - reply_button.ariaLabel = "Reply"; - reply_button.title = "Reply"; - reply_button.innerHTML = `🗨️${data.replies}`; - post_actions.appendChild(reply_button); - - const boost_button = document.createElement("button"); - boost_button.type = "button"; - boost_button.ariaLabel = "Boost"; - boost_button.title = "Boost"; - boost_button.innerHTML = `🔁${data.boosts}`; - post_actions.appendChild(boost_button); - - const fav_button = document.createElement("button"); - fav_button.type = "button"; - fav_button.ariaLabel = "Favourite"; - fav_button.title = "Favourite"; - fav_button.innerText = "⭐"; - post_actions.appendChild(fav_button); - - const react_button = document.createElement("button"); - react_button.type = "button"; - react_button.ariaLabel = "React"; - react_button.title = "React"; - react_button.innerText = "😃"; - post_actions.appendChild(react_button); - - const quote_button = document.createElement("button"); - quote_button.type = "button"; - quote_button.ariaLabel = "Quote"; - quote_button.title = "Quote"; - quote_button.innerText = "🗣️"; - post_actions.appendChild(quote_button); - - const more_button = document.createElement("button"); - more_button.type = "button"; - more_button.ariaLabel = "More"; - more_button.title = "More"; - more_button.innerText = "⚒️"; - post_actions.appendChild(more_button); - - post_footer.appendChild(post_actions); - - post_article.appendChild(post_footer); - - - post.appendChild(post_article); - - return post; -}; - -function hook_post_listeners(post) { - post.querySelectorAll("button").forEach(button => { - button.addEventListener("click", () => { - if (button.classList.contains("reaction")) { - toggle_reaction(button); - } - - switch (button.ariaLabel) { - case "Reply": - play_sound("post"); - break; - - case "Boost": - play_sound("boost"); - break; - - case "Favourite": - post.querySelectorAll("button.reaction").forEach(reaction => { - if (!reaction.innerText.startsWith("⭐")) return; - toggle_reaction(reaction); - }); - play_sound(); - break; - - default: - play_sound(); - break; - } - }); - }); -} - -function toggle_reaction(reaction) { - const was_active = reaction.classList.contains("active"); - reaction.classList.toggle("active"); - const count = reaction.querySelector(".count"); - count.innerText = Number(count.innerText) + (was_active ? -1 : 1); -} - -function load_content() { - for (let i = 0; i < 10; i++) { - const post = render_post(test_post); - feed.appendChild(post); - hook_post_listeners(post); - } -} - -function play_sound(name) { - if (!name) name = "default"; - const sound = sounds[name]; - if (!sound) { - console.warn(`Attempted to play sound "${name}", which does not exist!`); - return; - } - sound.pause(); - sound.currentTime = 0; - sound.play(); -} - -feed.querySelectorAll(".post-container").forEach(post => { - hook_post_listeners(post); -}); -load_content(); - -document.addEventListener("scroll", event => { - while (window.innerHeight + window.scrollY >= document.body.offsetHeight - 1000) { - load_content(); - } -}); diff --git a/src/App.svelte b/src/App.svelte new file mode 100644 index 0000000..49acc9a --- /dev/null +++ b/src/App.svelte @@ -0,0 +1,154 @@ + + +
+

space social

+

social media for the galaxy-wide-web! 🌌

+ +
+ +
+ {#if ready} + + {:else if !Instance.get_instance().ok} + +

this app requires a instance host and session token to work! you may enter these below:

+ +
(log_in(data))}> + + +
+ + +
+ +
+ +
+ +

how do i get these?

+
    +
  • + instance host refers to the domain of your fediverse instance. i.e. ice.arimelody.me. +
  • +
  • + a token is a unique code that grants applications permission to act on your behalf. + you can find it in your browser's cookies for your instance. + (instructions for firefox + and chrome) +
  • +
+ +

+ your login credentials will not be saved to an external server. + they are required for communication with the fediverse instance, and are saved entirely within your browser. + a cleaner login flow will be built in the future. +

+

+ oh yeah i should also probably mention this is extremely experimental software; + even if you use the exact same instance as me, you may encounter problems. + if that's all cool with you, welcome aboard! +

+ +

made with ❤️ by ari melody, 2024

+
+ {/if} +
+ +
+
+ + diff --git a/src/Error.svelte b/src/Error.svelte new file mode 100644 index 0000000..ab3fec2 --- /dev/null +++ b/src/Error.svelte @@ -0,0 +1,26 @@ + + +
+ {#if msg} +

{@html msg}

+ {/if} + {#if trace} +
{trace}
+ {/if} + +
+ + diff --git a/src/Feed.svelte b/src/Feed.svelte new file mode 100644 index 0000000..414341e --- /dev/null +++ b/src/Feed.svelte @@ -0,0 +1,49 @@ + + +
+ {#if error} + ')} /> + {/if} + {#each posts as post} + + {/each} +
diff --git a/src/app.css b/src/app.css new file mode 100644 index 0000000..6e36d45 --- /dev/null +++ b/src/app.css @@ -0,0 +1,20 @@ +@import url("/font/inter/inter.css"); + +:root { + --fg0: #eee; + --bg0: #080808; + --bg1: #101010; + --bg2: #121212; + --accent: #b7fd49; + --accent-bg: #242b1a; +} + +body { + margin: 0; + padding: 0; + + color: var(--fg0); + background-color: var(--bg0); + + font-family: "Inter", sans-serif; +} diff --git a/src/emoji.js b/src/emoji.js new file mode 100644 index 0000000..8206085 --- /dev/null +++ b/src/emoji.js @@ -0,0 +1,93 @@ +import Instance from './instance.js'; + +const EMOJI_REGEX = /:[a-z0-9_\-]+:/g; + +let emoji_cache = []; + +export default class Emoji { + name; + host; + url; + width; + height; + + static parse(data, host) { + const instance = Instance.get_instance(); + let emoji = null; + switch (instance.type) { + case Instance.types.ICESHRIMP: + emoji = Emoji.#parse_iceshrimp(data); + break; + case Instance.types.MASTODON: + emoji = Emoji.#parse_mastodon(data); + break; + default: + break; + } + if (emoji !== null) emoji_cache.push(emoji); + return emoji; + } + + static #parse_iceshrimp(data, host) { + let emoji = new Emoji() + emoji.name = data.name.substring(1, data.name.search('@')); + emoji.host = host; + emoji.url = data.url; + emoji.width = data.width; + emoji.height = data.height; + return emoji; + } + + static #parse_mastodon(data, host) { + let emoji = new Emoji() + emoji.name = data.shortcode; + emoji.host = host; + emoji.url = data.url; + emoji.width = data.width; + emoji.height = data.height; + return emoji; + } + + get id() { + return this.name + '@' + this.host; + } +} + +export function parse_text(text, ignore_instance) { + if (!text) return text; + + let index = text.search(EMOJI_REGEX); + if (index === -1) return text; + index++; + + // find the emoji name + let length = 0; + while (index + length < text.length && text[index + length] !== ':') length++; + let emoji_name = ':' + text.substring(index, index + length) + ':'; + + // does this emoji exist? + let emoji; + for (let cached in emoji_cache) { + if (cached.id === emoji_name) { + emoji = cached; + break; + } + } + + if (!emoji) return text.substring(0, index + length) + parse_text(text.substring(index + length)); + + // replace emoji code with + const img = `${emoji_name}`; + return text.substring(0, index - 1) + img + + parse(text.substring(index + length + 1), emojis, ignore_instance); +} + +export function parse_one(reaction, emojis) { + if (reaction == '❤') return '❤️'; // stupid heart unicode + if (!reaction.startsWith(':') || !reaction.endsWith(':')) return reaction; + for (let i = 0; i < emojis.length; i++) { + if (emojis[i].name == reaction.substring(1, reaction.length - 1)) + return `${emojis[i].name}`; + } + return reaction; +} diff --git a/src/instance.js b/src/instance.js new file mode 100644 index 0000000..334c369 --- /dev/null +++ b/src/instance.js @@ -0,0 +1,107 @@ +import Post from './post/post.js'; + +let instance; + +const ERR_UNSUPPORTED = "Unsupported server"; +const ERR_SERVER_RESPONSE = "Unsupported response from the server"; + +export default class Instance { + #host; + #token; + #type; + #secure; + + static types = { + ICESHRIMP: "iceshrimp", + MASTODON: "mastodon", + MISSKEY: "misskey", + AKKOMA: "akkoma", + }; + + static get_instance() { + if (!instance) instance = new Instance(); + return instance; + } + + static async setup(host, token, secure) { + instance = Instance.get_instance(); + instance.host = host; + instance.token = token; + instance.secure = secure; + await instance.#guess_type(); + } + + async #guess_type() { + const url = instance.#proto + instance.host + "/api/v1/instance"; + console.log("Snooping for instance information at " + url + "..."); + const res = await fetch(url); + const data = await res.json(); + const version = data.version.toLowerCase(); + + instance.type = Instance.types.MASTODON; + if (version.search("iceshrimp") !== -1) instance.type = Instance.types.ICESHRIMP; + if (version.search("misskey") !== -1) instance.type = Instance.types.MISSKEY; + if (version.search("akkoma") !== -1) instance.type = Instance.types.AKKOMA; + + console.log("Assumed server type to be \"" + instance.type + "\"."); + } + + static async get_timeline(last_post_id) { + let data = null; + switch (instance.type) { + case Instance.types.ICESHRIMP: + data = await instance.#get_timeline_iceshrimp(last_post_id); + break; + case Instance.types.MASTODON: + data = await instance.#get_timeline_mastodon(last_post_id); + break; + default: + console.error(ERR_UNSUPPORTED); + return null; + } + if (data.constructor != Array) { + console.error(ERR_SERVER_RESPONSE); + return null; + } + let posts = []; + data.forEach(post_data => { + const post = Post.parse(post_data); + if (!post) return; + posts = [...posts, post]; + }); + return posts; + } + + async #get_timeline_iceshrimp(last_post_id) { + let body = Object; + if (last_post_id) body.untilId = last_post_id; + const res = await fetch(this.#proto + this.host + "/api/notes/timeline", { + method: 'POST', + headers: { "Authorization": "Bearer " + this.token }, + body: JSON.stringify(body) + }); + return await res.json(); + } + + async #get_timeline_mastodon(last_post_id) { + let url = this.#proto + this.host + "/api/v1/timelines/home"; + if (last_post_id) url += "?max_id=" + last_post_id; + const res = await fetch(url, { + method: 'GET', + headers: { "Authorization": "Bearer " + this.token } + }); + return await res.json(); + } + + get #proto() { + if (this.secure) return "https://"; + return "http://"; + } + + static get ok() { + if (!instance) return false; + if (!instance.host) return false; + if (!instance.token) return false; + return true; + } +} diff --git a/src/main.js b/src/main.js new file mode 100644 index 0000000..f8b01de --- /dev/null +++ b/src/main.js @@ -0,0 +1,9 @@ +import './app.css'; +import App from './App.svelte'; +import Instance from './instance.js'; + +const app = new App({ + target: document.getElementById('app') +}); + +export default app; diff --git a/src/post/Body.svelte b/src/post/Body.svelte new file mode 100644 index 0000000..8152e5c --- /dev/null +++ b/src/post/Body.svelte @@ -0,0 +1,166 @@ + + +
+ {#if post.warning} +

{post.warning}

+ {/if} + {#if post.text} + {@html post.rich_text} + {/if} +
+ {#each post.files as file} +
+ + {file.alt} + +
+ {/each} +
+ {#if post.boost && post.text} +

this is quoting a post! quotes are not supported yet.

+ + {/if} +
+ + diff --git a/src/post/BoostContext.svelte b/src/post/BoostContext.svelte new file mode 100644 index 0000000..2aaf154 --- /dev/null +++ b/src/post/BoostContext.svelte @@ -0,0 +1,52 @@ + + +
+ 🔁 + + {@html parse_emojis(post.user.name, post.user.emojis, true)} boosted this post. + + + + +
+ + diff --git a/src/post/FooterButton.svelte b/src/post/FooterButton.svelte new file mode 100644 index 0000000..1d003bc --- /dev/null +++ b/src/post/FooterButton.svelte @@ -0,0 +1,54 @@ + + + + + diff --git a/src/post/Header.svelte b/src/post/Header.svelte new file mode 100644 index 0000000..0902849 --- /dev/null +++ b/src/post/Header.svelte @@ -0,0 +1,79 @@ + + +
+ + + +
+ + +
+
+ + diff --git a/src/post/Post.svelte b/src/post/Post.svelte new file mode 100644 index 0000000..6635fe5 --- /dev/null +++ b/src/post/Post.svelte @@ -0,0 +1,79 @@ + + +
+ {#if _post.reply} + + {/if} + {#if is_boost && !post_context.text} + + {/if} +
+
+ +
+
+ {#each Object.keys(_post.reactions) as reaction} + + {/each} +
+
+ + + + + + +
+
+
+
+ + diff --git a/src/post/ReplyContext.svelte b/src/post/ReplyContext.svelte new file mode 100644 index 0000000..ab19870 --- /dev/null +++ b/src/post/ReplyContext.svelte @@ -0,0 +1,130 @@ + + + + + diff --git a/src/post/post.js b/src/post/post.js new file mode 100644 index 0000000..45d001e --- /dev/null +++ b/src/post/post.js @@ -0,0 +1,220 @@ +import Instance from '../instance.js'; +import User from '../user/user.js'; + +import { parse_one as parse_emoji } from '../emoji.js'; + +let post_cache = Object; + +export default class Post { + id; + created_at; + user; + text; + warning; + boost_count; + reply_count; + mentions; + reactions; + emojis; + files; + url; + reply; + boost; + + static resolve_id(id) { + return post_cache[id] || null; + } + + static parse(data) { + const instance = Instance.get_instance(); + let post = null; + switch (instance.type) { + case Instance.types.ICESHRIMP: + post = Post.#parse_iceshrimp(data); + break; + case Instance.types.MASTODON: + post = Post.#parse_mastodon(data); + break; + default: + break; + } + if (!post) { + console.error("Error while parsing post data"); + return null; + } + post_cache[post.id] = post; + return post; + } + + static #parse_iceshrimp(data) { + let post = new Post() + post.id = data.id; + post.created_at = new Date(data.createdAt); + post.user = User.parse(data.user); + post.text = data.text; + post.warning = data.cw; + post.boost_count = data.renoteCount; + post.reply_count = data.repliesCount; + post.mentions = data.mentions; + post.reactions = data.reactions; + post.emojis = data.emojis; + post.files = data.files; + post.url = data.url; + post.boost = data.renote ? Post.parse(data.renote) : null; + post.reply = data.reply ? Post.parse(data.reply) : null; + return post; + } + + static #parse_mastodon(data) { + let post = new Post() + post.id = data.id; + post.created_at = new Date(data.created_at); + post.user = User.parse(data.account); + post.text = data.content; + post.warning = data.spoiler_text; + post.boost_count = data.reblogs_count; + post.reply_count = data.replies_count; + post.mentions = data.mentions; + post.reactions = data.reactions; + post.emojis = data.emojis; + post.files = data.media_attachments; + post.url = data.url; + post.boost = data.reblog ? Post.parse(data.reblog) : null; + post.reply = data.in_reply_to_id ? Post.resolve_id(data.in_reply_to_id) : null; + return post; + } + + get rich_text() { + let text = this.text; + if (!text) return text; + + const markdown_tokens = [ + { tag: "pre", token: "```" }, + { tag: "code", token: "`" }, + { tag: "strong", token: "**", regex: /\*{2}/g }, + { tag: "strong", token: "__" }, + { tag: "em", token: "*", regex: /\*/g }, + { tag: "em", token: "_" }, + ]; + + let response = ""; + let current; + let index = 0; + while (index < text.length) { + let sample = text.substring(index); + let allow_new = !current || !current.nostack; + + // handle newlines + if (allow_new && sample.startsWith('\n')) { + response += "
"; + index++; + continue; + } + + // handle mentions + if (allow_new && sample.match(/@[a-z0-9-_.]+@[a-z0-9-_.]+/g)) { + // find end of the mention + let length = 1; + while (index + length < text.length && /[a-z0-9-_.]/.test(text[index + length])) length++; + length++; // skim the middle @ + while (index + length < text.length && /[a-z0-9-_.]/.test(text[index + length])) length++; + + let mention = text.substring(index, index + length); + + // attempt to resolve mention to a user + let user = User.resolve_mention(mention); + if (user) { + const out = `` + + `` + + "@" + user.name + ""; + if (current) current.text += out; + else response += out; + } else { + response += mention; + } + index += mention.length; + continue; + } + + if (Instance.get_instance().type !== Instance.types.MASTODON) { + // handle links + if (allow_new && sample.match(/^[a-z]{3,6}:\/\/[^\s]+/g)) { + // get length of link + let length = text.substring(index).search(/\s|$/g); + let url = text.substring(index, index + length); + let out = `${url}`; + if (current) current.text += out; + else response += out; + index += length; + continue; + } + } + + // handle emojis + if (allow_new && sample.startsWith(':')) { + // lookahead to next invalid emoji character + let look = sample.substring(1).search(/[^a-zA-Z0-9-_.]/g) + 1; + // if it's ':', we can parse it + if (look !== 0 && sample[look] === ':') { + let emoji_code = sample.substring(0, look + 1); + let out = parse_emoji(emoji_code, this.emojis); + if (current) current.text += out; + else response += out; + index += emoji_code.length; + continue; + } + } + + // handle markdown + // TODO: handle misskey-flavoured markdown + if (current) { + // try to pop stack + if (sample.startsWith(current.token)) { + index += current.token.length; + let out = `<${current.tag}>${current.text}`; + if (current.token === '```') + out = `
${current.text}
`; + if (current.parent) current.parent.text += out; + else response += out; + current = current.parent; + } else { + current.text += sample[0]; + index++; + } + } else if (allow_new) { + // can we add to stack? + let pushed = false; + for (let i = 0; i < markdown_tokens.length; i++) { + let item = markdown_tokens[i]; + if (sample.startsWith(item.token)) { + let new_current = { + token: item.token, + tag: item.tag, + text: "", + parent: current, + }; + if (item.token === '```' || item.token === '`') new_current.nostack = true; + current = new_current; + pushed = true; + index += current.token.length; + break; + } + } + if (!pushed) { + response += sample[0]; + index++; + } + } + } + + // destroy the remaining stack + while (current) { + let out = current.token + current.text; + if (current.parent) current.parent.text += out; + else response += out; + current = current.parent; + } + + return response; + } +} diff --git a/src/sound.js b/src/sound.js new file mode 100644 index 0000000..bbbd62f --- /dev/null +++ b/src/sound.js @@ -0,0 +1,17 @@ +const sounds = { + "default": new Audio("sound/log.ogg"), + "post": new Audio("sound/success.ogg"), + "boost": new Audio("sound/hello.ogg"), +}; + +export function play_sound(name) { + if (!name) name = "default"; + const sound = sounds[name]; + if (!sound) { + console.warn(`Attempted to play sound "${name}", which does not exist!`); + return; + } + sound.pause(); + sound.currentTime = 0; + sound.play(); +} diff --git a/src/time.js b/src/time.js new file mode 100644 index 0000000..27ff200 --- /dev/null +++ b/src/time.js @@ -0,0 +1,23 @@ +const denoms = [ + { unit: 's', min: 0 }, + { unit: 'm', min: 60 }, + { unit: 'h', min: 60 }, + { unit: 'd', min: 24 }, + { unit: 'w', min: 7 }, + { unit: 'y', min: 52 }, +]; + +export function shorthand(date) { + let value = (new Date() - date) / 1000; + let unit = 's'; + let index = 0; + while (index < denoms.length - 1) { + if (value < denoms[index + 1].min) break; + index++ + value /= denoms[index].min; + unit = denoms[index].unit; + } + if (value > 0) + return Math.floor(value) + unit + " ago"; + return "in " + Math.floor(value) + unit; +} diff --git a/src/user/user.js b/src/user/user.js new file mode 100644 index 0000000..2a8a803 --- /dev/null +++ b/src/user/user.js @@ -0,0 +1,83 @@ +import Instance from '../instance.js'; +import Emoji from '../emoji.js'; + +let user_cache = Object; + +export default class User { + id; + nickname; + username; + host; + avatar_url; + emojis; + + static resolve_id(id) { + return user_cache[id]; + } + + static resolve_mention(mention) { + for (let i = 0; i < Object.keys(user_cache).length; i++) { + let user = user_cache[Object.keys(user_cache)[i]]; + if (user.mention === mention) return user; + } + } + + static parse(data) { + const instance = Instance.get_instance(); + let user = null; + switch (instance.type) { + case Instance.types.ICESHRIMP: + user = User.#parse_iceshrimp(data); + break; + case Instance.types.MASTODON: + user = User.#parse_mastodon(data); + break; + default: + break; + } + if (!user) { + console.error("Error while parsing user data"); + return null; + } + user_cache[user.id] = user; + return user; + } + + static #parse_iceshrimp(data) { + let user = new User(); + user.id = data.id; + user.nickname = data.name; + user.username = data.username; + user.host = data.host || Instance.get_instance().host; + user.avatar_url = data.avatarUrl; + user.emojis = []; + data.emojis.forEach(emoji => { + user.emojis.push(Emoji.parse(emoji, user.host)); + }); + return user; + } + + static #parse_mastodon(data) { + let user = new User(); + user.id = data.id; + user.nickname = data.display_name; + user.username = data.username; + user.host = data.acct.search('@') ? data.acct.substring(data.acct.search('@') + 1) : instance.host; + user.avatar_url = data.avatar; + user.emojis = []; + data.emojis.forEach(emoji => { + user.emojis.push(Emoji.parse(emoji, user.host)); + }); + return user; + } + + get name() { + return this.nickname || this.username; + } + + get mention() { + let res = "@" + this.username; + if (this.host) res += "@" + this.host; + return res; + } +} diff --git a/svelte.config.js b/svelte.config.js new file mode 100644 index 0000000..61eb947 --- /dev/null +++ b/svelte.config.js @@ -0,0 +1,7 @@ +import { vitePreprocess } from '@sveltejs/vite-plugin-svelte' + +export default { + // Consult https://svelte.dev/docs#compile-time-svelte-preprocess + // for more information about preprocessors + preprocess: vitePreprocess(), +} diff --git a/vite.config.js b/vite.config.js new file mode 100644 index 0000000..5f1c8cb --- /dev/null +++ b/vite.config.js @@ -0,0 +1,7 @@ +import { defineConfig } from 'vite' +import { svelte } from '@sveltejs/vite-plugin-svelte' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [svelte()], +})