first commit
This commit is contained in:
commit
b5a4c0a601
42 changed files with 2802 additions and 0 deletions
56
.forgejo/workflows/build.yaml
Normal file
56
.forgejo/workflows/build.yaml
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
name: Build
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Build
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repo
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Setup Node
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
|
||||||
|
- name: Cache npm dependencies
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: '~/.npm'
|
||||||
|
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-node-
|
||||||
|
|
||||||
|
- name: Build project
|
||||||
|
run: npm install && npm run build
|
||||||
|
|
||||||
|
- name: Upload production-ready build files
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: production-files
|
||||||
|
path: ./dist
|
||||||
|
|
||||||
|
deploy:
|
||||||
|
name: Deploy
|
||||||
|
needs: build
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Download artifact
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: production-files
|
||||||
|
path: ./dist
|
||||||
|
|
||||||
|
- name: Upload ftp
|
||||||
|
uses: https://git.lgbt/mirror/ftp-action@releases/v2
|
||||||
|
with:
|
||||||
|
host: ${{ secrets.FTP_SERVER }}
|
||||||
|
user: ${{ secrets.FTP_USER }}
|
||||||
|
password: ${{ secrets.FTP_PASSWORD }}
|
||||||
|
localDir: "dist"
|
||||||
|
remoteDir: "v2.exhq.dev"
|
||||||
|
options: "--delete"
|
24
.gitignore
vendored
Normal file
24
.gitignore
vendored
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
dist-ssr
|
||||||
|
*.local
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
|
.DS_Store
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
28
README.md
Normal file
28
README.md
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ npm install # or pnpm install or yarn install
|
||||||
|
```
|
||||||
|
|
||||||
|
### Learn more on the [Solid Website](https://solidjs.com) and come chat with us on our [Discord](https://discord.com/invite/solidjs)
|
||||||
|
|
||||||
|
## Available Scripts
|
||||||
|
|
||||||
|
In the project directory, you can run:
|
||||||
|
|
||||||
|
### `npm run dev`
|
||||||
|
|
||||||
|
Runs the app in the development mode.<br>
|
||||||
|
Open [http://localhost:5173](http://localhost:5173) to view it in the browser.
|
||||||
|
|
||||||
|
### `npm run build`
|
||||||
|
|
||||||
|
Builds the app for production to the `dist` folder.<br>
|
||||||
|
It correctly bundles Solid in production mode and optimizes the build for the best performance.
|
||||||
|
|
||||||
|
The build is minified and the filenames include the hashes.<br>
|
||||||
|
Your app is ready to be deployed!
|
||||||
|
|
||||||
|
## Deployment
|
||||||
|
|
||||||
|
Learn more about deploying your application with the [documentations](https://vitejs.dev/guide/static-deploy.html)
|
21
hacked/App.tsx
Normal file
21
hacked/App.tsx
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import '../src/App.css'
|
||||||
|
import './hacked.css'
|
||||||
|
export default function App() {
|
||||||
|
return <div class='hackedmain'>
|
||||||
|
<div class='hackedheader'>
|
||||||
|
<h1>websites that ive stolen</h1>
|
||||||
|
<div class='hackedlist'>
|
||||||
|
<a href="https://exhq.mugman.tech/">exhq.mugman.tech</a>
|
||||||
|
<a href="https://exhq.nekos.in/">exhq.nekos.in</a>
|
||||||
|
<a href="https://exhq.i386.dev">exhq.i386.dev</a>
|
||||||
|
<a href="https://exhq.sadan.zip">exhq.sadan.zip</a>
|
||||||
|
<a href="https://exhq.maggiepi.site">exhq.maggiepi.site</a>
|
||||||
|
<a href="https://exhq.nea.moe">exhq.nea.moe</a>
|
||||||
|
<a href="https://exhq.ushie.dev">exhq.ushie.dev</a>
|
||||||
|
<a href="https://exhq.aspy.dev">exhq.aspy.dev</a>
|
||||||
|
<a href="https://exhq.steamcumunity.com/">exhq.steamcumunity.com</a>
|
||||||
|
<a href="https://exhq.rico040.su/">exhq.rico040.su</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
18
hacked/hacked.css
Normal file
18
hacked/hacked.css
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
.hackedmain {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.hackedheader {
|
||||||
|
font-size: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hackedlist a {
|
||||||
|
color: pink;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hackedlist {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
17
hacked/index.html
Normal file
17
hacked/index.html
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="icon" type="image/svg+xml" href="https://proxy.spiro.exhq.dev/_/plain/https://dp.nea.moe/avatar/712639419785412668.png" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>amy hacked</title>
|
||||||
|
<meta content="i am hakcer" property="og:title" />
|
||||||
|
<meta content="wevbsiutres that ive st0oplen" property="og:description" />
|
||||||
|
<meta content="https://proxy.spiro.exhq.dev/_/plain/https://dp.nea.moe/avatar/712639419785412668.png" property="og:image" />
|
||||||
|
<meta content="#43B581" data-react-helmet="true" name="theme-color" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="hackedroot"></div>
|
||||||
|
<script type="module" src="./index.tsx"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
11
hacked/index.tsx
Normal file
11
hacked/index.tsx
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import { render } from 'solid-js/web'
|
||||||
|
|
||||||
|
import App from './App'
|
||||||
|
|
||||||
|
const root = document.getElementById('hackedroot')
|
||||||
|
|
||||||
|
render(() => (
|
||||||
|
<>
|
||||||
|
<App />
|
||||||
|
</>
|
||||||
|
), root!)
|
24
index.html
Normal file
24
index.html
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link
|
||||||
|
rel="icon"
|
||||||
|
type="image/svg+xml"
|
||||||
|
href="https://files.amy.rip/pfp.jpg"
|
||||||
|
/>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Amy</title>
|
||||||
|
<meta content="Amy" property="og:title" />
|
||||||
|
<meta
|
||||||
|
content="warning: this user is known to be extremely amy, proceed with caution."
|
||||||
|
property="og:description"
|
||||||
|
/>
|
||||||
|
<meta content="https://files.amy.rip/pfp.jpg" property="og:image" />
|
||||||
|
<meta content="#43B581" data-react-helmet="true" name="theme-color" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="root"></div>
|
||||||
|
<script type="module" src="/src/index.tsx"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
21
package.json
Normal file
21
package.json
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"name": "v2.exhq.dev",
|
||||||
|
"private": true,
|
||||||
|
"version": "0.0.0",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "tsc -b && vite build",
|
||||||
|
"preview": "vite preview"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "^20.14.10",
|
||||||
|
"solid-js": "^1.8.17"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"typescript": "^5.2.2",
|
||||||
|
"vite": "^5.3.1",
|
||||||
|
"vite-plugin-solid": "^2.10.2"
|
||||||
|
},
|
||||||
|
"packageManager": "pnpm@9.12.3+sha512.cce0f9de9c5a7c95bef944169cc5dfe8741abfb145078c0d508b868056848a87c81e626246cb60967cbd7fd29a6c062ef73ff840d96b3c86c40ac92cf4a813ee"
|
||||||
|
}
|
1142
pnpm-lock.yaml
Normal file
1142
pnpm-lock.yaml
Normal file
File diff suppressed because it is too large
Load diff
BIN
public/birthday.png
Normal file
BIN
public/birthday.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.2 KiB |
BIN
public/explod.gif
Normal file
BIN
public/explod.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
BIN
public/explod.mp3
Normal file
BIN
public/explod.mp3
Normal file
Binary file not shown.
BIN
public/fireemoji.png
Normal file
BIN
public/fireemoji.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 928 B |
BIN
public/fjonkie.png
Executable file
BIN
public/fjonkie.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
BIN
public/gaybackground.png
Normal file
BIN
public/gaybackground.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.3 KiB |
BIN
public/nyaboom.webp
Normal file
BIN
public/nyaboom.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.2 KiB |
51
review/App.tsx
Normal file
51
review/App.tsx
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
import '../src/App.css'
|
||||||
|
import "./reviewed.css"
|
||||||
|
import { sendReview } from '../src/components/api'
|
||||||
|
|
||||||
|
export default function App() {
|
||||||
|
const token = window.location.hash.substring(window.location.hash.indexOf("access_token") + "access_token".length + 1).substring(0, 30)
|
||||||
|
console.log(token)
|
||||||
|
if (token === "") {
|
||||||
|
window.location.href = "https://discord.com/oauth2/authorize?client_id=1208380910525743134&response_type=token&redirect_uri=https%3A%2F%2Fexhq.dev%2Freview%2F&scope=identify"
|
||||||
|
}
|
||||||
|
let ref!: HTMLTextAreaElement;
|
||||||
|
return <div class='reviewOuterparent'>
|
||||||
|
<div class='reviewParent'>
|
||||||
|
<img src="../fjonkie.png" alt="" />
|
||||||
|
<span>(it doesnt)</span>
|
||||||
|
<textarea
|
||||||
|
ref={ref}
|
||||||
|
onKeyPress={async (e) => {
|
||||||
|
if (e.key === "Enter") {
|
||||||
|
e.preventDefault()
|
||||||
|
if (await sendReview(ref.value, token)) {
|
||||||
|
alert("review sent!")
|
||||||
|
} else {
|
||||||
|
alert("something went wrong, check your network tab or something idfk")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
placeholder='your shitty review'
|
||||||
|
class='reviewText'
|
||||||
|
name="" id="" cols="25" rows="3">
|
||||||
|
</textarea>
|
||||||
|
|
||||||
|
<div class='flexButton'>
|
||||||
|
<button onclick={async () => {
|
||||||
|
try {
|
||||||
|
const success = await sendReview(ref.value, token);
|
||||||
|
if (success) {
|
||||||
|
alert("Review sent successfully!");
|
||||||
|
} else {
|
||||||
|
alert("Failed to send review. open your browser's network tab for more info lmao");
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
alert("how");
|
||||||
|
}
|
||||||
|
|
||||||
|
}} class='sendButton'>send yo shi</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
20
review/index.html
Normal file
20
review/index.html
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="icon" type="image/svg+xml" href="https://proxy.spiro.exhq.dev/_/plain/https://dp.nea.moe/avatar/712639419785412668.png" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>amy reviews</title>
|
||||||
|
<meta content="review" property="og:title" />
|
||||||
|
<meta content="rewviewdb, but not turkish" property="og:description" />
|
||||||
|
<meta content="https://proxy.spiro.exhq.dev/_/plain/https://dp.nea.moe/avatar/712639419785412668.png" property="og:image" />
|
||||||
|
<meta content="#43B581" data-react-helmet="true" name="theme-color" />
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="reviewroot"></div>
|
||||||
|
<script type="module" src="./index.tsx"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
11
review/index.tsx
Normal file
11
review/index.tsx
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import { render } from 'solid-js/web'
|
||||||
|
|
||||||
|
import App from './App'
|
||||||
|
|
||||||
|
const root = document.getElementById('reviewroot')
|
||||||
|
|
||||||
|
render(() => (
|
||||||
|
<>
|
||||||
|
<App />
|
||||||
|
</>
|
||||||
|
), root!)
|
54
review/reviewed.css
Normal file
54
review/reviewed.css
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
textarea {
|
||||||
|
resize: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.parent {
|
||||||
|
height: 100%;
|
||||||
|
/* just */
|
||||||
|
}
|
||||||
|
|
||||||
|
.reviewOuterparent {
|
||||||
|
height: 90vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-around;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reviewText {
|
||||||
|
margin-top: 15%;
|
||||||
|
color: pink;
|
||||||
|
margin-bottom: 10%;
|
||||||
|
font-size: xx-large;
|
||||||
|
background-color: #1e1e1e;
|
||||||
|
font-family: monospace;
|
||||||
|
outline: none;
|
||||||
|
border: none;
|
||||||
|
text-align: center;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reviewParent {
|
||||||
|
display: flex;
|
||||||
|
/* background-color: ; */
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sendButton {
|
||||||
|
color: pink;
|
||||||
|
background-color: #0a0a0a;
|
||||||
|
font-size: 19px;
|
||||||
|
border: 2px solid #0a0a0a;
|
||||||
|
padding: 15px 50px;
|
||||||
|
cursor: pointer
|
||||||
|
}
|
||||||
|
.sendButton:hover {
|
||||||
|
background-color: #2c2c2c;
|
||||||
|
border: 2px solid #2c2c2c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flexButton {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
417
src/App.css
Normal file
417
src/App.css
Normal file
|
@ -0,0 +1,417 @@
|
||||||
|
:root {
|
||||||
|
-webkit-touch-callout: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-khtml-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
/* browsers agreeing on stuff challenge (impossible) */
|
||||||
|
background-color: #121212;
|
||||||
|
font-family: monospace;
|
||||||
|
overflow-x: hidden;
|
||||||
|
color: #ffc8dd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer a {
|
||||||
|
color: #cdb4db;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
margin: 10px;
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.musicartist {
|
||||||
|
font-weight: bolder;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.musicbutton {
|
||||||
|
background-color: #272525;
|
||||||
|
color: pink;
|
||||||
|
font-family: Roboto, sans-serif;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 10px 30px;
|
||||||
|
box-shadow: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
transition: 639ms;
|
||||||
|
transform: translateY(0);
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
border: none;
|
||||||
|
margin: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.musicdiv {
|
||||||
|
background-color: rgba(0, 0, 0, 0.731);
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
z-index: 1500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.music-close-button-div {
|
||||||
|
display: flex;
|
||||||
|
justify-content: end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-button {
|
||||||
|
padding: 2;
|
||||||
|
border: none;
|
||||||
|
background: none;
|
||||||
|
border-radius: 2px;
|
||||||
|
background-color: #5e5a5a;
|
||||||
|
text-decoration: none;
|
||||||
|
color: pink;
|
||||||
|
cursor: pointer;
|
||||||
|
margin: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.musiclist {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
font-size: larger;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
height: 80%;
|
||||||
|
overflow-x: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
.innermusic {
|
||||||
|
width: 50%;
|
||||||
|
height: 50%;
|
||||||
|
border-radius: 2%;
|
||||||
|
background: #121212;
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.musicbutton:hover {
|
||||||
|
border-radius: 5px;
|
||||||
|
transition: 639ms;
|
||||||
|
padding: 10px 30px;
|
||||||
|
transform: translateY(-1px);
|
||||||
|
border: none;
|
||||||
|
box-shadow: 0 0 534px -3px rgba(250, 236, 236, 0.4);
|
||||||
|
-webkit-box-shadow: 0 0 534px -3px rgba(250, 236, 236, 0.4);
|
||||||
|
-moz-box-shadow: 0 0 534px -3px rgba(250, 236, 236, 0.4);
|
||||||
|
background-color: #5e5a5a;
|
||||||
|
animation: big 500ms infinite;
|
||||||
|
transform: translateY(-0.3em);
|
||||||
|
transition:
|
||||||
|
background-color 1s,
|
||||||
|
transform 0.5s,
|
||||||
|
box-shadow 0.5s,
|
||||||
|
-webkit-box-shadow 0.5s,
|
||||||
|
-moz-box-shadow 0.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actualreviewdiv {
|
||||||
|
overflow-y: scroll;
|
||||||
|
height: 18em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cardchild:hover + .actualreviewdiv {
|
||||||
|
transition: 1s;
|
||||||
|
transform: rotateY(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
margin-top: 6em;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cardchild h1:not(:has(.listeningto)) {
|
||||||
|
font-size: 3em;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reviewheadertext {
|
||||||
|
margin-bottom: -0.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cardchild p {
|
||||||
|
margin-bottom: -1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cardchild a {
|
||||||
|
font-size: 1.5em;
|
||||||
|
text-align: center;
|
||||||
|
color: pink;
|
||||||
|
text-decoration: underline;
|
||||||
|
margin-bottom: 0%;
|
||||||
|
.fadein {
|
||||||
|
animation: spawntop 1s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cardchild span {
|
||||||
|
font-size: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cardchild img {
|
||||||
|
max-width: 5em;
|
||||||
|
margin: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cardchild:hover::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CAN BROWSERS JUST AGREE ON ONE FUCKING THING */
|
||||||
|
|
||||||
|
.cardchild {
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
scrollbar-width: none;
|
||||||
|
cursor: default;
|
||||||
|
background-color: #272525;
|
||||||
|
border-radius: 5%;
|
||||||
|
width: 25em;
|
||||||
|
height: 25em;
|
||||||
|
margin-top: 1em;
|
||||||
|
padding: 0.5em 5em 2em 5em;
|
||||||
|
transform: translateY(-0em);
|
||||||
|
transition:
|
||||||
|
background-color 1s,
|
||||||
|
transform 0.5s,
|
||||||
|
box-shadow 0.5s,
|
||||||
|
-webkit-box-shadow 0.5s,
|
||||||
|
-moz-box-shadow 0.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theeaster {
|
||||||
|
color: pink;
|
||||||
|
padding: 8px;
|
||||||
|
font-size: 21px;
|
||||||
|
text-align: center;
|
||||||
|
border-width: 0;
|
||||||
|
background-color: #5555557a;
|
||||||
|
border-style: solid;
|
||||||
|
border-radius: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theeaster:focus {
|
||||||
|
border-color: pink;
|
||||||
|
box-shadow: 0 0 534px -3px rgba(250, 236, 236, 0.4);
|
||||||
|
-webkit-box-shadow: 0 0 534px -3px rgba(250, 236, 236, 0.4);
|
||||||
|
-moz-box-shadow: 0 0 534px -3px rgba(250, 236, 236, 0.4);
|
||||||
|
transition: 0.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.easteregg {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.easteregginner {
|
||||||
|
width: 70%;
|
||||||
|
background-color: #272525;
|
||||||
|
height: 10em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cardchild:hover {
|
||||||
|
box-shadow: 0 0 534px -3px rgba(250, 236, 236, 0.4);
|
||||||
|
-webkit-box-shadow: 0 0 534px -3px rgba(250, 236, 236, 0.4);
|
||||||
|
-moz-box-shadow: 0 0 534px -3px rgba(250, 236, 236, 0.4);
|
||||||
|
background-color: #5e5a5a;
|
||||||
|
animation: big 500ms infinite;
|
||||||
|
transform: translateY(-0.3em);
|
||||||
|
transition:
|
||||||
|
background-color 1s,
|
||||||
|
transform 0.5s,
|
||||||
|
box-shadow 0.5s,
|
||||||
|
-webkit-box-shadow 0.5s,
|
||||||
|
-moz-box-shadow 0.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.linktree {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
}
|
||||||
|
|
||||||
|
.linktree img {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.singlereview img {
|
||||||
|
border-radius: 12%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.singlereview {
|
||||||
|
margin: 1em;
|
||||||
|
border-radius: 3%;
|
||||||
|
background-color: #00000040;
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cssishard {
|
||||||
|
background-color: #121212;
|
||||||
|
}
|
||||||
|
|
||||||
|
.singlemusic {
|
||||||
|
cursor: pointer;
|
||||||
|
min-width: 15em;
|
||||||
|
max-width: 15em;
|
||||||
|
word-wrap: anywhere;
|
||||||
|
margin: 1em;
|
||||||
|
padding: 1em;
|
||||||
|
border-radius: 3%;
|
||||||
|
background-color: #272525;
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.singlemusic img {
|
||||||
|
max-width: 5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.innermusic {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reviewname {
|
||||||
|
margin-bottom: 0.1em;
|
||||||
|
font-weight: bolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reviewinfo {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reviewname {
|
||||||
|
margin-bottom: 0.1em;
|
||||||
|
font-weight: bolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
.parent {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header h1 {
|
||||||
|
font-size: 3.6em;
|
||||||
|
color: blanchedalmond;
|
||||||
|
display: inline-table;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cardchild h2 {
|
||||||
|
display: inline-table;
|
||||||
|
vertical-align: text-bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header h1:not(:active) {
|
||||||
|
animation: slide-right 1.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header h1:hover {
|
||||||
|
animation: shake 10ms infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header img {
|
||||||
|
border-radius: 25%;
|
||||||
|
margin-right: 1em;
|
||||||
|
vertical-align: middle;
|
||||||
|
max-width: 10em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.initialanim {
|
||||||
|
animation: slide-left 1.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gaybackground {
|
||||||
|
background-image: url("/gaybackground.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate {
|
||||||
|
z-index: 10000000;
|
||||||
|
transform: scale(10000);
|
||||||
|
transition: 20s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes slide-left {
|
||||||
|
from {
|
||||||
|
transform: translateX(-10000em);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes slide-right {
|
||||||
|
from {
|
||||||
|
transform: translateX(10000em);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes bigsmall {
|
||||||
|
0% {
|
||||||
|
max-width: 10em;
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
width: 10.5em;
|
||||||
|
max-width: 10.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
max-width: 10em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spawntop {
|
||||||
|
0% {
|
||||||
|
opacity: 0%;
|
||||||
|
transform: translateY(1em);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 100%;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes shake {
|
||||||
|
0% {
|
||||||
|
transform: translate(0, 0) rotate(0deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
25% {
|
||||||
|
transform: translate(5px, 5px) rotate(5deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
transform: translate(0, 0) rotate(0eg);
|
||||||
|
}
|
||||||
|
|
||||||
|
75% {
|
||||||
|
transform: translate(-5px, 5px) rotate(-5deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
transform: translate(0, 0) rotate(0deg);
|
||||||
|
}
|
||||||
|
}
|
255
src/App.tsx
Normal file
255
src/App.tsx
Normal file
|
@ -0,0 +1,255 @@
|
||||||
|
import './App.css'
|
||||||
|
import {AdvancedBr, Singular88, SingularOomfie} from './components/comps.tsx'
|
||||||
|
import {createSignal, onMount} from 'solid-js';
|
||||||
|
import Reviews from './components/api.tsx';
|
||||||
|
import Music, {MusicEntry} from './components/music.tsx';
|
||||||
|
import {Bdpfp, Normalpfp} from './components/pfp.tsx';
|
||||||
|
import {InfoCard} from './components/middlecard.tsx';
|
||||||
|
|
||||||
|
export const [shouldpopup, setpopup] = createSignal(false)
|
||||||
|
export const [shouldpopup88, setpopup88] = createSignal(false)
|
||||||
|
export const [shouldpopupEasterEgg, setpopupEasterEgg] = createSignal(false)
|
||||||
|
export const [ishover, setishover] = createSignal(false)
|
||||||
|
|
||||||
|
let explodcount = 0
|
||||||
|
const isitmybd = () => new Date().toISOString().slice(5, 10) === '08-22';
|
||||||
|
|
||||||
|
function getRandomVivsieWord() {
|
||||||
|
const words = [
|
||||||
|
"fuck",
|
||||||
|
"shit",
|
||||||
|
"pussy",
|
||||||
|
"penis",
|
||||||
|
"dick"
|
||||||
|
]
|
||||||
|
return words[Math.floor(Math.random() * words.length)]
|
||||||
|
}
|
||||||
|
|
||||||
|
function vivsiepop() {
|
||||||
|
const blep = document.body.childNodes;
|
||||||
|
|
||||||
|
function fuckshit(node: ChildNode) {
|
||||||
|
if (node.nodeType === Node.TEXT_NODE) {
|
||||||
|
node.textContent = getRandomVivsieWord();
|
||||||
|
} else {
|
||||||
|
node.childNodes.forEach(fuckshit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blep.forEach(fuckshit)
|
||||||
|
}
|
||||||
|
|
||||||
|
function nyaboom() {
|
||||||
|
explodcount++
|
||||||
|
const blep = document.body.childNodes;
|
||||||
|
|
||||||
|
function fuckshit(node: ChildNode) {
|
||||||
|
if (node.nodeType === Node.TEXT_NODE) {
|
||||||
|
(node as Element).textContent = ''
|
||||||
|
node.parentElement?.appendChild(<img style={{
|
||||||
|
width: "1.5em"
|
||||||
|
}} src="./explod.gif"/> as Element)
|
||||||
|
} else if (node instanceof HTMLImageElement) {
|
||||||
|
node.src = "./explod.gif"
|
||||||
|
} else {
|
||||||
|
node.childNodes.forEach(fuckshit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blep.forEach(fuckshit)
|
||||||
|
}
|
||||||
|
|
||||||
|
function App() {
|
||||||
|
|
||||||
|
const [musicList, setMusicList] = createSignal<string[]>([]);
|
||||||
|
const [isLoading, setIsLoading] = createSignal(true);
|
||||||
|
const [oomfies, setoomfies] = createSignal(<>oomfies</>)
|
||||||
|
const [isAnimating, setIsAnimating] = createSignal(false);
|
||||||
|
onMount(async () => {
|
||||||
|
try {
|
||||||
|
const response = await fetch("https://imtoolazytomakeaproperapi.exhq.dev/");
|
||||||
|
const data = await response.json();
|
||||||
|
setMusicList(data);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching music data:", error);
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let gitgay = <img onClick={() => {
|
||||||
|
setIsAnimating(true)
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.href = "https://git.lgbt/exhq"
|
||||||
|
}, 200);
|
||||||
|
gitgay.src = "/gaybackground.png"
|
||||||
|
}} classList={{'gitgayimg': true, 'animate': isAnimating(), 'gaybackground': isAnimating()}}
|
||||||
|
src="https://proxy.spiro.exhq.dev/_/plain/https://git.lgbt/assets/img/logo.png"
|
||||||
|
alt="logo of git.lgbt"/> as HTMLImageElement
|
||||||
|
// @ts-ignore
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{isitmybd() ? <Bdpfp setpopupEasterEgg={setpopupEasterEgg}/> :
|
||||||
|
<Normalpfp setpopupEasterEgg={setpopupEasterEgg}/>}
|
||||||
|
|
||||||
|
<p style={{display: "none"}}>AdvancedBr my beloved</p>
|
||||||
|
<AdvancedBr count={6}/>
|
||||||
|
|
||||||
|
|
||||||
|
<div class='parent'>
|
||||||
|
<div class='cardchild'>
|
||||||
|
<h1>link tree</h1>
|
||||||
|
<div class='linktree'>
|
||||||
|
{gitgay}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<br/>
|
||||||
|
<div class='linktree'>
|
||||||
|
<span class='gitgaytext'>Git</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{
|
||||||
|
opacity: isAnimating() ? "0%" : "100%"
|
||||||
|
}} class='cardchild'>
|
||||||
|
<InfoCard bd={isitmybd()}/>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
onMouseEnter={() => {
|
||||||
|
setishover(true)
|
||||||
|
}}
|
||||||
|
onmouseleave={() => {
|
||||||
|
setishover(false)
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
opacity: isAnimating() ? "0%" : "100%"
|
||||||
|
}} class='cardchild'>
|
||||||
|
<Reviews/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<AdvancedBr count={2}/>
|
||||||
|
<div class='easteregg' style={{opacity: isAnimating() ? "0%" : "100%"}}>
|
||||||
|
<div class="musicbutton" onClick={() => {
|
||||||
|
setpopup(!shouldpopup())
|
||||||
|
}}>
|
||||||
|
<p>typa shit ive been on</p><img style={{
|
||||||
|
"margin-left": "0.3em",
|
||||||
|
"max-width": "1.5em"
|
||||||
|
}} src="./fireemoji.png"/>
|
||||||
|
</div>
|
||||||
|
<div class="musicbutton">
|
||||||
|
<div class="oomfies" onClick={() => {
|
||||||
|
setoomfies(
|
||||||
|
<>
|
||||||
|
<SingularOomfie name='ashley' discordid='836177139798638592'
|
||||||
|
url='https://ashleygraves.eu/'></SingularOomfie>
|
||||||
|
<SingularOomfie name='nea' discordid='310702108997320705'
|
||||||
|
url='https://nea.moe'></SingularOomfie>
|
||||||
|
<SingularOomfie name='vozy' discordid='359175647257690113'
|
||||||
|
url='https://vozy.exhq.dev'></SingularOomfie>
|
||||||
|
<SingularOomfie name='hazel' discordid='435026627907420161'
|
||||||
|
url='https://yellows.ink/'></SingularOomfie>
|
||||||
|
<SingularOomfie name='nax' discordid='148801388938264576'
|
||||||
|
url='https://nax.dev/'></SingularOomfie>
|
||||||
|
<SingularOomfie name='squirrelly' discordid='218032723296649217'
|
||||||
|
url='https://squirrelly13.neocities.org/'></SingularOomfie>
|
||||||
|
<SingularOomfie name='ushie' discordid='399862294143696897'
|
||||||
|
url='https://ushie.dev/'></SingularOomfie>
|
||||||
|
<SingularOomfie name='mugman' discordid='601836455006044163'
|
||||||
|
url='https://mugman.tech'></SingularOomfie>
|
||||||
|
<SingularOomfie name='krystal' discordid='929208515883569182'
|
||||||
|
url='https://krystal.exhq.dev/'></SingularOomfie>
|
||||||
|
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}}> {oomfies()}</div>
|
||||||
|
</div>
|
||||||
|
<div class="musicbutton" onClick={vivsiepop}>
|
||||||
|
<p>echo if it was written by vivsiepop</p>
|
||||||
|
</div>
|
||||||
|
<div class="musicbutton" onClick={() => {
|
||||||
|
setpopup88(true)
|
||||||
|
}}>
|
||||||
|
<p>88x31's</p>
|
||||||
|
</div>
|
||||||
|
<div class="musicbutton" onClick={() => {
|
||||||
|
if (explodcount > 5) {
|
||||||
|
document.body.innerHTML = ""
|
||||||
|
setTimeout(() => {
|
||||||
|
alert("sorry bud, you exploded so much that my document.body is gon")
|
||||||
|
}, 500)
|
||||||
|
} else {
|
||||||
|
new Audio("./explod.mp3").play()
|
||||||
|
nyaboom()
|
||||||
|
}
|
||||||
|
}}>
|
||||||
|
<img style={{
|
||||||
|
"margin-left": "0.3em",
|
||||||
|
"max-width": "1.5em"
|
||||||
|
}} src="./nyaboom.webp"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<AdvancedBr count={3}/>
|
||||||
|
<Music shouldpopup={shouldpopup}>
|
||||||
|
<div class='musicdiv'>
|
||||||
|
<div class='innermusic'>
|
||||||
|
<div class="music-close-button-div">
|
||||||
|
<button class="close-button" onClick={() => {
|
||||||
|
setpopup(false)
|
||||||
|
}}>X
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class='musiclist'>
|
||||||
|
{isLoading() ? (
|
||||||
|
<p>Loading...</p>
|
||||||
|
) : (
|
||||||
|
musicList().map((link) => <MusicEntry spotifylink={link}/>)
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Music>
|
||||||
|
<Music shouldpopup={shouldpopupEasterEgg}>
|
||||||
|
<div class='musicdiv'>
|
||||||
|
<div class='innermusic'>
|
||||||
|
<div class="music-close-button-div">
|
||||||
|
<button class="close-button" onClick={() => {
|
||||||
|
setpopupEasterEgg(false)
|
||||||
|
}}>X
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<img src={"https://pico.exhq.dev/-Aax47Gmdsy"}/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Music>
|
||||||
|
<Music shouldpopup={shouldpopup88}>
|
||||||
|
<div class='musicdiv'>
|
||||||
|
<div class='innermusic'>
|
||||||
|
<div class="music-close-button-div">
|
||||||
|
<button class="close-button" onClick={() => {
|
||||||
|
setpopup88(false)
|
||||||
|
}}>X
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div style={{}}>
|
||||||
|
<img src="https://exhq.dev/88x31.png" alt=""/>
|
||||||
|
<br/>
|
||||||
|
<span>feel free to link mine, <code>https://exhq.dev/88x31.png</code></span>
|
||||||
|
<div style={{"background-color": "gray", height: "1px"}}/>
|
||||||
|
<div>
|
||||||
|
<Singular88 name="nax" url="https://nax.dev" src="https://nax.dev/88x31.gif"/>
|
||||||
|
<Singular88 name="sophari" url="https://sophari.org" src="https://sophari.org/img/sophari.gif"/>
|
||||||
|
<Singular88 name="rini" url="https://rinici.de/" src="https://rinici.de/button.png"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Music>
|
||||||
|
<div class='footer'> <a href="https://ko-fi.com/amyarson">support me ♥</a><br/>made with ♥ by amy. <a
|
||||||
|
href="https://git.lgbt/exhq/v2.exhq.dev">this website is
|
||||||
|
opensource</a></div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default App
|
115
src/components/api.tsx
Normal file
115
src/components/api.tsx
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
import {createSignal, onMount} from "solid-js"
|
||||||
|
import {ishover} from "../App";
|
||||||
|
|
||||||
|
interface Review {
|
||||||
|
reviewID: number;
|
||||||
|
discordID: string;
|
||||||
|
reviewText: string;
|
||||||
|
timestamp: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface NeoReview extends Review {
|
||||||
|
global_name: string;
|
||||||
|
username: string
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default function Reviews() {
|
||||||
|
const [reviews, setReviews] = createSignal<NeoReview[]>([]);
|
||||||
|
onMount(() => {
|
||||||
|
fetch("https://review.exhq.dev/getreviews")
|
||||||
|
.then(response => response.json())
|
||||||
|
.then((data: Review[]) => {
|
||||||
|
const promises = data.map(review => (
|
||||||
|
fetch(`https://dc-lookup.spiro.exhq.dev/v1/user/${review.discordID}`)
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(user => ({
|
||||||
|
...review,
|
||||||
|
global_name: user.global_name,
|
||||||
|
username: user.username
|
||||||
|
}))
|
||||||
|
));
|
||||||
|
|
||||||
|
Promise.all(promises)
|
||||||
|
.then(yeah => {
|
||||||
|
setReviews(yeah);
|
||||||
|
})
|
||||||
|
.catch(error => console.error("Error fetching Discord user data:", error));
|
||||||
|
})
|
||||||
|
.catch(error => console.error("Error fetching reviews:", error));
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<a style={{
|
||||||
|
display: ishover() ? "inline" : "none"
|
||||||
|
}}
|
||||||
|
href="https://discord.com/oauth2/authorize?client_id=1208380910525743134&response_type=token&redirect_uri=https%3A%2F%2Fexhq.dev%2Freview%2F&scope=identify">
|
||||||
|
<p class="fadein">add your reviews here</p>
|
||||||
|
</a>
|
||||||
|
<h1 class="reviewheadertext">Reviews</h1>
|
||||||
|
<div
|
||||||
|
class="actualreviewdiv">
|
||||||
|
{reviews().length > 0 ? (
|
||||||
|
reviews().reverse().map((review) => (
|
||||||
|
<div>
|
||||||
|
<SingleReview {...review} />
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<div>Loading reviews...</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export const theImager = async (id: string): Promise<string> => (await fetch(`https://dc-lookup.spiro.exhq.dev/v1/user/${id}`)
|
||||||
|
.then(res => res.json()).then(data => "https://proxy.spiro.exhq.dev/_/plain/"+data.avatar.link).catch(() => "https://http.cat/status/100"));
|
||||||
|
|
||||||
|
function SingleReview(props: NeoReview) {
|
||||||
|
const [imageSrc, setImageSrc] = createSignal("");
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
const url = await theImager(props.discordID);
|
||||||
|
setImageSrc(url);
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div class="singlereview">
|
||||||
|
<img
|
||||||
|
src={imageSrc()}
|
||||||
|
alt="User Avatar"
|
||||||
|
style={{"max-width": "3em", "border-radius": "30%"}}
|
||||||
|
/>
|
||||||
|
<div class="reviewinfo">
|
||||||
|
<div class="reviewname">
|
||||||
|
{props.global_name === null ? props.username : props.global_name}
|
||||||
|
</div>
|
||||||
|
<div class="reviewtext">{props.reviewText}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function sendReview(review: string, token: string): Promise<boolean> {
|
||||||
|
try {
|
||||||
|
const response = await fetch(`https://review.exhq.dev/sendreview?review=${review}`, {
|
||||||
|
headers: {
|
||||||
|
"Auth": token,
|
||||||
|
},
|
||||||
|
method: "POST"
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.status !== 200) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
9
src/components/comps.css
Normal file
9
src/components/comps.css
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
|
||||||
|
.tooltip:hover {
|
||||||
|
max-width: 4em !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip {
|
||||||
|
animation: ease-in-out 2s infinite;
|
||||||
|
padding: 1em;
|
||||||
|
}
|
67
src/components/comps.tsx
Normal file
67
src/components/comps.tsx
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
import { createSignal, onMount } from "solid-js";
|
||||||
|
import { theImager } from "./api"
|
||||||
|
import "./comps.css"
|
||||||
|
// warning: this IS horrible code. its a joke. DO NOT try this at home because
|
||||||
|
// your local senior programmer CAN and WILL hunt you down
|
||||||
|
// you have been warned.
|
||||||
|
export function AdvancedBr({ count }: { count: number }) {
|
||||||
|
return new Array(count).fill(null).map(_ => (<br />))
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SingularOomfie(props: { name: string; url: string; discordid: string }) {
|
||||||
|
const [imageSrc, setImageSrc] = createSignal("");
|
||||||
|
const [showTooltip, setShowTooltip] = createSignal(false);
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
const url = await theImager(props.discordid);
|
||||||
|
setImageSrc(url);
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleMouseMove = () => {
|
||||||
|
setShowTooltip(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleMouseLeave = () => {
|
||||||
|
setShowTooltip(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
onMouseMove={handleMouseMove}
|
||||||
|
onMouseLeave={handleMouseLeave}
|
||||||
|
style={{ position: "relative", display: "inline-block" }}
|
||||||
|
>
|
||||||
|
<a href={props.url}>
|
||||||
|
<img
|
||||||
|
class="tooltip"
|
||||||
|
style={{
|
||||||
|
"max-width": "3em",
|
||||||
|
"border-radius": "30%",
|
||||||
|
}}
|
||||||
|
src={imageSrc()}
|
||||||
|
alt={"profile picture for " + props.name}
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
{showTooltip() && (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
position: "absolute",
|
||||||
|
background: "rgba(0, 0, 0, 0.7)",
|
||||||
|
color: "white",
|
||||||
|
padding: "0.5em",
|
||||||
|
"border-radius": "5px",
|
||||||
|
"pointer-events": "none",
|
||||||
|
transform: "translate(20%, -100%)",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{props.name}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function Singular88(props: { name: string; url: string; src:string }) {
|
||||||
|
return <a href={props.url}><img alt={props.name} src={props.src}/></a>
|
||||||
|
}
|
6
src/components/cumbrainz.css
Normal file
6
src/components/cumbrainz.css
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
.listeningto {
|
||||||
|
font-size: smaller;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
65
src/components/cumbrainz.tsx
Normal file
65
src/components/cumbrainz.tsx
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
import {createSignal, onMount, Show} from "solid-js";
|
||||||
|
import "./cumbrainz.css"
|
||||||
|
|
||||||
|
|
||||||
|
interface ListenPayload {
|
||||||
|
payload: {
|
||||||
|
count: number;
|
||||||
|
listens: Listen[];
|
||||||
|
playing_now: boolean;
|
||||||
|
user_id: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Listen {
|
||||||
|
playing_now: boolean;
|
||||||
|
track_metadata: TrackMetadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TrackMetadata {
|
||||||
|
additional_info: AdditionalInfo;
|
||||||
|
artist_name: string;
|
||||||
|
release_name: string;
|
||||||
|
track_name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AdditionalInfo {
|
||||||
|
duration: number;
|
||||||
|
music_service_name: string;
|
||||||
|
origin_url: string;
|
||||||
|
submission_client: string;
|
||||||
|
submission_client_version: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Cumbrainz() {
|
||||||
|
const [musicInfo, setMusicInfo] = createSignal({} as ListenPayload);
|
||||||
|
const [isLoading, setIsLoading] = createSignal(true);
|
||||||
|
onMount(async () => {
|
||||||
|
try {
|
||||||
|
const the = await fetch("https://music.exhq.dev/")
|
||||||
|
const thejson = await the.json()
|
||||||
|
setMusicInfo(thejson)
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching music data from song.link:", error);
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return <div class="listeningto">
|
||||||
|
<h2 >Listening to</h2>
|
||||||
|
<Show when={isLoading()} fallback={
|
||||||
|
<Show when={musicInfo().payload.listens.length > 0} fallback={<span>nothing</span>}>
|
||||||
|
<Thesong song={musicInfo()} />
|
||||||
|
</Show>
|
||||||
|
}>
|
||||||
|
<span>loading</span>
|
||||||
|
</Show>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
function Thesong({song}: { song: ListenPayload }) {
|
||||||
|
return <a
|
||||||
|
href={song.payload.listens[0].track_metadata.additional_info.origin_url.replace(/\?.*/, m => `?v=${new URLSearchParams(m).get('v') ?? ''}`).replace(/(\?v=)$/, '')}>
|
||||||
|
<div> {song.payload.listens[0].track_metadata.artist_name} - {song.payload.listens[0].track_metadata.track_name} </div>
|
||||||
|
</a>
|
||||||
|
}
|
21
src/components/events.tsx
Normal file
21
src/components/events.tsx
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import { onMount } from 'solid-js';
|
||||||
|
|
||||||
|
const ReloadOnBack = () => {
|
||||||
|
const handlePageShow = (event: Event) => {
|
||||||
|
const pageshowEvent = event as PageTransitionEvent;
|
||||||
|
if (pageshowEvent.persisted) {
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
window.addEventListener('pageshow', handlePageShow);
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener('pageshow', handlePageShow);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ReloadOnBack;
|
11
src/components/middlecard.css
Normal file
11
src/components/middlecard.css
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
.middleparent {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.middlechild {
|
||||||
|
text-align: center;
|
||||||
|
}
|
33
src/components/middlecard.tsx
Normal file
33
src/components/middlecard.tsx
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
import { Cumbrainz } from "./cumbrainz"
|
||||||
|
import "./middlecard.css"
|
||||||
|
export interface InfoCardProps {
|
||||||
|
bd: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export function InfoCard(props: InfoCardProps) {
|
||||||
|
|
||||||
|
return <div class="middleparent">
|
||||||
|
<div class="middlechild">{
|
||||||
|
props.bd ?
|
||||||
|
<>
|
||||||
|
<span>
|
||||||
|
its my birthday
|
||||||
|
<br />
|
||||||
|
please buy me stuff
|
||||||
|
</span>
|
||||||
|
</> : <>
|
||||||
|
<span>silly goober who does silly stuff
|
||||||
|
<br />
|
||||||
|
self proclaimed programmer and progamer
|
||||||
|
<br />
|
||||||
|
shitposts for fun
|
||||||
|
</span>
|
||||||
|
</>}</div>
|
||||||
|
<div style={{"background-color": "gray", height: "1px"}}>
|
||||||
|
<br/>
|
||||||
|
</div>
|
||||||
|
<div class="middlechild">
|
||||||
|
<Cumbrainz></Cumbrainz>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
47
src/components/music.tsx
Normal file
47
src/components/music.tsx
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
import { createSignal, onMount } from "solid-js";
|
||||||
|
|
||||||
|
export default function Music(props: { shouldpopup: () => boolean, children: any }) {
|
||||||
|
return <div style={{
|
||||||
|
position: "absolute",
|
||||||
|
display: props.shouldpopup() ? "block" : "none"
|
||||||
|
}}>
|
||||||
|
{props.children}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
export function MusicEntry({ spotifylink }: { spotifylink: string }) {
|
||||||
|
const [musicInfo, setMusicInfo] = createSignal({}) as any;
|
||||||
|
const [isLoading, setIsLoading] = createSignal(true);
|
||||||
|
onMount(async () => {
|
||||||
|
try {
|
||||||
|
const apiresponse = await fetch(`https://corsisdum.exhq.dev/v1-alpha.1/links?url=spotify%253Atrack%253A${spotifylink}`)
|
||||||
|
const data = await apiresponse.json()
|
||||||
|
setMusicInfo(data)
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching music data from song.link:", error);
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return (
|
||||||
|
<>{isLoading() ? (
|
||||||
|
<p>Loading...</p>
|
||||||
|
) : (
|
||||||
|
<div onClick={() => {
|
||||||
|
document.location.href = musicInfo().pageUrl
|
||||||
|
}} class="singlemusic">
|
||||||
|
<img style={{
|
||||||
|
"margin-right": "0.5em"
|
||||||
|
}} src={"https://proxy.spiro.exhq.dev/_/plain/" + musicInfo().entitiesByUniqueId[`SPOTIFY_SONG::${spotifylink}`]?.thumbnailUrl} alt={"album cover of" + musicInfo().entitiesByUniqueId[`SPOTIFY_SONG::${spotifylink}`]?.title} />
|
||||||
|
<div class="innersinglemusic">
|
||||||
|
<div class="musicartist" > {
|
||||||
|
musicInfo().entitiesByUniqueId[`SPOTIFY_SONG::${spotifylink}`]?.artistName?.length > 43 ? musicInfo().entitiesByUniqueId[`SPOTIFY_SONG::${spotifylink}`]?.artistName.substring(0, 30) + "..." : musicInfo().entitiesByUniqueId[`SPOTIFY_SONG::${spotifylink}`]?.artistName
|
||||||
|
}</div>
|
||||||
|
<div class="musictitle"> {
|
||||||
|
musicInfo().entitiesByUniqueId[`SPOTIFY_SONG::${spotifylink}`]?.title?.length > 43 ? musicInfo().entitiesByUniqueId[`SPOTIFY_SONG::${spotifylink}`]?.title.substring(0, 30) + "..." : musicInfo().entitiesByUniqueId[`SPOTIFY_SONG::${spotifylink}`]?.title
|
||||||
|
} </div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}</>
|
||||||
|
)
|
||||||
|
}
|
31
src/components/name.tsx
Normal file
31
src/components/name.tsx
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// import { createSignal, onCleanup } from "solid-js";
|
||||||
|
import { onCleanup } from "solid-js";
|
||||||
|
import { removethething } from "./utils.tsx";
|
||||||
|
|
||||||
|
function HoverComponent() {
|
||||||
|
let timerId: number | null;
|
||||||
|
|
||||||
|
const clearTimer = () => {
|
||||||
|
if (timerId) {
|
||||||
|
clearTimeout(timerId);
|
||||||
|
timerId = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onCleanup(() => {
|
||||||
|
clearTimer();
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<h1
|
||||||
|
class="removethisinstantly"
|
||||||
|
onMouseEnter={() => {
|
||||||
|
removethething();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Amy
|
||||||
|
</h1>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default HoverComponent;
|
40
src/components/pfp.css
Normal file
40
src/components/pfp.css
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
.birthdayparent {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes rotateAnimation {
|
||||||
|
from {
|
||||||
|
transform: rotateY(0deg);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: rotateY(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.rotate {
|
||||||
|
animation: rotateAnimation 0.5s ease-in-out forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header .bd {
|
||||||
|
flex-direction: column;
|
||||||
|
margin-left: 10em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.birthday {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
margin-left: -12em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.birthdaypfp {
|
||||||
|
z-index: 1;
|
||||||
|
max-width: 10em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.birthdayhat {
|
||||||
|
z-index: 2;
|
||||||
|
width: 14em;
|
||||||
|
top: -3em;
|
||||||
|
left: -1em;
|
||||||
|
}
|
69
src/components/pfp.tsx
Normal file
69
src/components/pfp.tsx
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
import HoverComponent from "./name";
|
||||||
|
import "./pfp.css";
|
||||||
|
|
||||||
|
export function Bdpfp({
|
||||||
|
setpopupEasterEgg,
|
||||||
|
}: {
|
||||||
|
setpopupEasterEgg: (value: boolean) => void;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
onContextMenu={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
setpopupEasterEgg(true);
|
||||||
|
}}
|
||||||
|
class="header bd"
|
||||||
|
>
|
||||||
|
<div class="birthdayparent">
|
||||||
|
<img
|
||||||
|
class="birthdaypfp birthday"
|
||||||
|
src="https://files.amy.rip/pfp.jpg"
|
||||||
|
alt="amy's current discord pfp, with a birthday hat on it"
|
||||||
|
/>
|
||||||
|
<img class="birthdayhat birthday" src="./birthday.png" alt="" />
|
||||||
|
<HoverComponent />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Normalpfp({
|
||||||
|
setpopupEasterEgg,
|
||||||
|
}: {
|
||||||
|
setpopupEasterEgg: (value: boolean) => void;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
onContextMenu={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
setpopupEasterEgg(true);
|
||||||
|
}}
|
||||||
|
class="birthdayparent header normal"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
class="initialanim"
|
||||||
|
src="https://files.amy.rip/pfp.jpg"
|
||||||
|
alt="amy's current discord pfp"
|
||||||
|
onMouseEnter={(e) => {
|
||||||
|
(e.target as HTMLImageElement).animate(
|
||||||
|
[{ transform: "rotateZ(0deg)" }, { transform: "rotateZ(360deg)" }],
|
||||||
|
{
|
||||||
|
duration: 400,
|
||||||
|
iterations: 1,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
onClick={(e) => {
|
||||||
|
(e.target as HTMLImageElement).animate(
|
||||||
|
[{ transform: "rotateY(0deg)" }, { transform: "rotateY(360deg)" }],
|
||||||
|
{
|
||||||
|
duration: 150,
|
||||||
|
iterations: 1,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<HoverComponent />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
35
src/components/utils.tsx
Normal file
35
src/components/utils.tsx
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
export function removethething() {
|
||||||
|
for (let i = 0; i < document.styleSheets.length; i++) {
|
||||||
|
let styleSheet = document.styleSheets[i];
|
||||||
|
let rules = styleSheet.cssRules || styleSheet.rules;
|
||||||
|
for (let j = 0; j < rules.length; j++) {
|
||||||
|
let rule = rules[j];
|
||||||
|
if (rule.type === CSSRule.KEYFRAMES_RULE && ((rule as CSSKeyframesRule).name === "slide-right" )) {
|
||||||
|
styleSheet.deleteRule(j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// export interface song {
|
||||||
|
// entitiesByUniqueId: {
|
||||||
|
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
export async function getLatestItems(apiUrl: string) {
|
||||||
|
try {
|
||||||
|
const response = await fetch(apiUrl);
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`API call failed with status ${response.status}`);
|
||||||
|
}
|
||||||
|
const data = await response.json();
|
||||||
|
if (!Array.isArray(data)) {
|
||||||
|
throw new Error('API response is not an array');
|
||||||
|
}
|
||||||
|
const lastFive = data.slice(-5);
|
||||||
|
return lastFive;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching data:', error);
|
||||||
|
}
|
||||||
|
}
|
14
src/index.tsx
Normal file
14
src/index.tsx
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
/* @refresh reload */
|
||||||
|
import { render } from 'solid-js/web'
|
||||||
|
|
||||||
|
import App from './App'
|
||||||
|
import ReloadOnBack from './components/events'
|
||||||
|
|
||||||
|
const root = document.getElementById('root')
|
||||||
|
|
||||||
|
render(() => (
|
||||||
|
<>
|
||||||
|
<ReloadOnBack />
|
||||||
|
<App />
|
||||||
|
</>
|
||||||
|
), root!)
|
1
src/vite-env.d.ts
vendored
Normal file
1
src/vite-env.d.ts
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/// <reference types="vite/client" />
|
28
tsconfig.app.json
Normal file
28
tsconfig.app.json
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"composite": true,
|
||||||
|
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
||||||
|
"target": "ES2020",
|
||||||
|
"useDefineForClassFields": true,
|
||||||
|
"module": "ESNext",
|
||||||
|
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||||
|
"skipLibCheck": true,
|
||||||
|
|
||||||
|
/* Bundler mode */
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"moduleDetection": "force",
|
||||||
|
"noEmit": true,
|
||||||
|
"jsx": "preserve",
|
||||||
|
"jsxImportSource": "solid-js",
|
||||||
|
|
||||||
|
/* Linting */
|
||||||
|
"strict": true,
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"noUnusedParameters": true,
|
||||||
|
"noFallthroughCasesInSwitch": true
|
||||||
|
},
|
||||||
|
"include": ["src", "hacked", "review"]
|
||||||
|
}
|
11
tsconfig.json
Normal file
11
tsconfig.json
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"files": [],
|
||||||
|
"references": [
|
||||||
|
{
|
||||||
|
"path": "./tsconfig.app.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "./tsconfig.node.json"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
13
tsconfig.node.json
Normal file
13
tsconfig.node.json
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"composite": true,
|
||||||
|
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"strict": true,
|
||||||
|
"noEmit": true
|
||||||
|
},
|
||||||
|
"include": ["vite.config.ts"]
|
||||||
|
}
|
16
vite.config.ts
Normal file
16
vite.config.ts
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import { defineConfig } from 'vite'
|
||||||
|
import { resolve } from 'path'
|
||||||
|
import solid from 'vite-plugin-solid'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
build: {
|
||||||
|
rollupOptions: {
|
||||||
|
input: {
|
||||||
|
main: resolve(__dirname, 'index.html'),
|
||||||
|
hacked: resolve(__dirname, 'hacked/index.html'),
|
||||||
|
review: resolve(__dirname, 'review/index.html')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
plugins: [solid()],
|
||||||
|
})
|
Loading…
Reference in a new issue