first commit
This commit is contained in:
commit
15d5df3227
13
.editorconfig
Normal file
13
.editorconfig
Normal file
@ -0,0 +1,13 @@
|
||||
# editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
94
.gitignore
vendored
Normal file
94
.gitignore
vendored
Normal file
@ -0,0 +1,94 @@
|
||||
# Created by .ignore support plugin (hsz.mobi)
|
||||
### Node template
|
||||
# Logs
|
||||
/logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
|
||||
# next.js build output
|
||||
.next
|
||||
|
||||
# nuxt.js build output
|
||||
.nuxt
|
||||
|
||||
# Nuxt generate
|
||||
dist
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# Serverless directories
|
||||
.serverless
|
||||
|
||||
# IDE / Editor
|
||||
.idea
|
||||
|
||||
# Service worker
|
||||
sw.*
|
||||
|
||||
# macOS
|
||||
.DS_Store
|
||||
|
||||
# Vim swap files
|
||||
*.swp
|
||||
|
||||
# db file
|
||||
db.json
|
||||
pass
|
12
README.md
Normal file
12
README.md
Normal file
@ -0,0 +1,12 @@
|
||||
# My Website - [ngn13.fun](https://ngn13.fun)
|
||||
This repo contains the source code of my personal website.
|
||||
It's written NuxtJS and supports full SSR.
|
||||
|
||||
## Setup
|
||||
```
|
||||
git clone https://github.com/ngn13/my-website.git
|
||||
cd my-website && npm i
|
||||
echo "password" > pass
|
||||
npm run build
|
||||
npm run start
|
||||
```
|
78
api/db.js
Normal file
78
api/db.js
Normal file
@ -0,0 +1,78 @@
|
||||
const fs = require("fs");
|
||||
|
||||
class Database {
|
||||
constructor() {
|
||||
this.path = "db.json";
|
||||
this.json = {};
|
||||
this.read();
|
||||
}
|
||||
|
||||
write() {
|
||||
fs.writeFileSync(this.path, JSON.stringify(this.json));
|
||||
}
|
||||
|
||||
read() {
|
||||
try {
|
||||
const data = fs.readFileSync(this.path, "utf8");
|
||||
this.json = JSON.parse(data);
|
||||
} catch (error) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
find_all(key, check, ...args) {
|
||||
try {
|
||||
const ret = [];
|
||||
for (const d of this.json[key]) {
|
||||
if (check(d, ...args)) {
|
||||
ret.push(d);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
find(key, check, ...args) {
|
||||
try {
|
||||
for (const d of this.json[key]) {
|
||||
if (check(d, ...args)) {
|
||||
return d;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
get(key) {
|
||||
const res = this.json[key]
|
||||
if(res===undefined)
|
||||
return []
|
||||
return res
|
||||
}
|
||||
|
||||
push(key, data) {
|
||||
try {
|
||||
this.json[key].push(data);
|
||||
} catch (error) {
|
||||
this.json[key] = [];
|
||||
this.json[key].push(data);
|
||||
}
|
||||
this.write();
|
||||
}
|
||||
|
||||
pop(key, data) {
|
||||
try {
|
||||
const indx = this.json[key].indexOf(data);
|
||||
this.json[key].splice(indx, 1);
|
||||
} catch (error) {
|
||||
return;
|
||||
}
|
||||
this.write();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Database;
|
136
api/index.js
Normal file
136
api/index.js
Normal file
@ -0,0 +1,136 @@
|
||||
const express = require("express");
|
||||
const fs = require("fs");
|
||||
const Database = require("./db");
|
||||
|
||||
const app = express();
|
||||
const db = new Database();
|
||||
|
||||
app.use(express.json());
|
||||
app.use(express.urlencoded({ extended: false }));
|
||||
|
||||
function gimmeToken() {
|
||||
var result = ""
|
||||
var characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
|
||||
var charactersLength = characters.length
|
||||
for ( var i = 0; i < 32; i++ ) {
|
||||
result += characters.charAt(Math.floor(Math.random() * charactersLength));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
let TOKEN = gimmeToken();
|
||||
const PASS = fs.readFileSync("pass", "utf-8")
|
||||
|
||||
/*
|
||||
* error: 0 -> no error
|
||||
* error: 1 -> parameter error
|
||||
* error: 2 -> auth error
|
||||
*
|
||||
*/
|
||||
|
||||
// PATH: /api/login
|
||||
// METHOD: GET
|
||||
// PARAMETERS: pass
|
||||
app.get("/login", (req,res)=>{
|
||||
let pass = req.query.pass;
|
||||
|
||||
if (pass === undefined)
|
||||
return res.json({error: 1})
|
||||
|
||||
if (pass !== PASS)
|
||||
return res.json({error: 2})
|
||||
|
||||
res.json({error: 0, token:TOKEN})
|
||||
})
|
||||
|
||||
// PATH: /api/logout
|
||||
// METHOD: GET
|
||||
// PARAMETERS: token
|
||||
app.get("/logout", (req,res)=>{
|
||||
let token = req.query.token;
|
||||
|
||||
if (token === undefined)
|
||||
return res.json({error: 1})
|
||||
|
||||
if (token !== TOKEN)
|
||||
return res.json({error: 2})
|
||||
|
||||
TOKEN = gimmeToken()
|
||||
res.json({error: 0})
|
||||
})
|
||||
|
||||
// PATH: /api/add_project
|
||||
// METHOD: GET
|
||||
// PARAMETERS: token, name, desc, url
|
||||
app.get("/add_project", (req, res) => {
|
||||
let token = req.query.token;
|
||||
let name = req.query.name;
|
||||
let desc = req.query.desc;
|
||||
let url = req.query.url;
|
||||
|
||||
if (
|
||||
token === undefined ||
|
||||
name === undefined ||
|
||||
desc === undefined ||
|
||||
url === undefined
|
||||
)
|
||||
return res.json({error: 1})
|
||||
|
||||
if (token !== TOKEN)
|
||||
return res.json({error: 2})
|
||||
|
||||
db.push("projects", {"name":name, "desc":desc, "url":url})
|
||||
res.json({error: 0})
|
||||
});
|
||||
|
||||
// PATH: /api/add_resource
|
||||
// METHOD: GET
|
||||
// PARAMETERS: token, name, tags, url
|
||||
app.get("/add_resource", (req, res) => {
|
||||
let token = req.query.token;
|
||||
let name = req.query.name;
|
||||
let tags = req.query.tags;
|
||||
let url = req.query.url;
|
||||
|
||||
if (
|
||||
token === undefined ||
|
||||
name === undefined ||
|
||||
tags === undefined ||
|
||||
url === undefined
|
||||
)
|
||||
return res.json({error: 1})
|
||||
|
||||
if (token !== TOKEN)
|
||||
return res.json({error: 2})
|
||||
|
||||
db.push("resources", {"name":name, "tags":tags.split(","), "url":url})
|
||||
res.json({error: 0})
|
||||
});
|
||||
|
||||
// PATH: /api/get_projects
|
||||
// METHOD: GET
|
||||
// PARAMETERS: NONE
|
||||
app.get("/get_projects", (req, res) => {
|
||||
let projects = db.get("projects")
|
||||
res.json({error: 0, projects:projects})
|
||||
});
|
||||
|
||||
// PATH: /api/get_resources
|
||||
// METHOD: GET
|
||||
// PARAMETERS: NONE
|
||||
app.get("/get_resources", (req, res) => {
|
||||
let resources = db.get("resources")
|
||||
res.json({error: 0, resources:resources})
|
||||
});
|
||||
|
||||
// PATH: /api/ping
|
||||
// METHOD: GET
|
||||
// PARAMETERS: NONE
|
||||
app.get("/ping", (req, res) => {
|
||||
res.send({ error: 0 });
|
||||
});
|
||||
|
||||
export default {
|
||||
path: "/api",
|
||||
handler: app,
|
||||
};
|
29
components/Button.vue
Normal file
29
components/Button.vue
Normal file
@ -0,0 +1,29 @@
|
||||
<template>
|
||||
<button @click="click"><slot></slot></button>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ["click"]
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
button {
|
||||
text-align: center;
|
||||
width: 540px;
|
||||
font-size: 25px;
|
||||
padding: 20px;
|
||||
border-radius: 20px;
|
||||
background: var(--dark-two);
|
||||
border: none;
|
||||
color: white;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
transition: .4s;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
box-shadow: var(--def-shadow);
|
||||
}
|
||||
</style>
|
56
components/Card.vue
Normal file
56
components/Card.vue
Normal file
@ -0,0 +1,56 @@
|
||||
<template>
|
||||
<div>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
div {
|
||||
box-shadow: var(--def-shadow);
|
||||
background: var(--dark-two);
|
||||
width: 100%;
|
||||
height: auto;
|
||||
padding: 50px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-shadow: 3px 4px 7px rgba(81, 67, 21, 0.8);
|
||||
font-size: 50px;
|
||||
margin-bottom: 30px;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
i {
|
||||
animation-name: colorAnimation;
|
||||
animation-duration: 10s;
|
||||
animation-iteration-count: infinite;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
i {
|
||||
font-size: 30px;
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 40px;
|
||||
line-height: 60px;
|
||||
}
|
||||
|
||||
a {
|
||||
font-size: 40px;
|
||||
color: white;
|
||||
line-height: 60px;
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
31
components/Header.vue
Normal file
31
components/Header.vue
Normal file
@ -0,0 +1,31 @@
|
||||
<template>
|
||||
<div class="header">
|
||||
<h1>
|
||||
<slot></slot>
|
||||
</h1>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
div {
|
||||
background: linear-gradient(rgba(3, 3, 3, 0.706), rgba(22, 22, 22, 0.808)), url("https://www.sketchappsources.com/resources/source-image/tv-glitch-sureshmurali29.png");
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-weight: 900;
|
||||
font-size: 7.5vw;
|
||||
padding: 150px;
|
||||
text-align: center;
|
||||
color: white;
|
||||
text-shadow: 3px 4px 7px rgba(81, 67, 21, 0.8);
|
||||
text-size-adjust: 80%;
|
||||
}
|
||||
</style>
|
27
components/Input.vue
Normal file
27
components/Input.vue
Normal file
@ -0,0 +1,27 @@
|
||||
<template>
|
||||
<input v-on:keyup="keyup" :placeholder="placeholder" :type="type">
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props:["keyup", "placeholder", "type"]
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
input {
|
||||
width: 500px;
|
||||
font-size: 25px;
|
||||
padding: 20px;
|
||||
border-radius: 20px;
|
||||
background: var(--dark-two);
|
||||
border: none;
|
||||
color: white;
|
||||
outline: none;
|
||||
transition: .4s;
|
||||
}
|
||||
|
||||
input:focus {
|
||||
box-shadow: var(--def-shadow);
|
||||
}
|
||||
</style>
|
41
components/Logout.vue
Normal file
41
components/Logout.vue
Normal file
@ -0,0 +1,41 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Currently logged in</h1>
|
||||
<Button :click="click">Logout</Button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios';
|
||||
import Button from './Button.vue';
|
||||
|
||||
export default {
|
||||
methods: {
|
||||
async click(e) {
|
||||
await axios.get(`/api/logout?token=${localStorage.getItem("token")}`)
|
||||
localStorage.clear()
|
||||
location.reload()
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
h1{
|
||||
color: var(--white);
|
||||
font-size: 50px;
|
||||
margin-bottom: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
div{
|
||||
background-color: var(--dark-three);
|
||||
padding: 50px;
|
||||
margin-top: 50px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
53
components/Navbar.vue
Normal file
53
components/Navbar.vue
Normal file
@ -0,0 +1,53 @@
|
||||
<template>
|
||||
<nav>
|
||||
<div>
|
||||
<h3>[ngn]</h3>
|
||||
</div>
|
||||
<div>
|
||||
<NavbarLink :out="false" url="/">Home</NavbarLink>
|
||||
<NavbarLink :out="false" url="/projects">Projects</NavbarLink>
|
||||
<NavbarLink :out="false" url="/resources">Resources</NavbarLink>
|
||||
<!--<NavbarLink :out="false" url="/stats">Stats</NavbarLink>-->
|
||||
<NavbarLink :out="true" url="http://github.com/ngn13/my-website">Source</NavbarLink>
|
||||
</div>
|
||||
</nav>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import NavbarLink from "./NavbarLink.vue";
|
||||
|
||||
export default {}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
nav {
|
||||
background: var(--dark-two);
|
||||
padding: 25px 35px 30px 35px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
border-bottom: solid 3px black;
|
||||
animation-name: borderAnimation;
|
||||
animation-duration: 10s;
|
||||
animation-iteration-count: infinite;
|
||||
box-shadow: var(--def-shadow);
|
||||
}
|
||||
|
||||
div {
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-weight: 900;
|
||||
font-size: 30px;
|
||||
color: red;
|
||||
animation-name: colorAnimation;
|
||||
animation-iteration-count: infinite;
|
||||
animation-duration: 10s;
|
||||
}
|
||||
</style>
|
60
components/NavbarLink.vue
Normal file
60
components/NavbarLink.vue
Normal file
@ -0,0 +1,60 @@
|
||||
<template>
|
||||
<div>
|
||||
<nuxt-link v-if="!out" :class="cname" id="link" :to="url">
|
||||
<slot></slot>
|
||||
</nuxt-link>
|
||||
<a v-if="out" :class="cname" id="link" :href="url">
|
||||
<slot></slot>
|
||||
</a>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ["url", "out"],
|
||||
data() {
|
||||
return {
|
||||
cname: "notcurrent"
|
||||
}
|
||||
},
|
||||
mounted(){
|
||||
let url = window.location.pathname
|
||||
if(url===this.url){
|
||||
this.cname = "current"
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.notcurrent {
|
||||
margin-left: 20px;
|
||||
font-weight: 700;
|
||||
font-size: 25px;
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.notcurrent:hover {
|
||||
text-decoration: underline;
|
||||
animation-name: underlineAnimation;
|
||||
animation-duration: 5s;
|
||||
animation-iteration-count: infinite;
|
||||
text-shadow: 3px 4px 7px rgba(81, 67, 21, 0.8);
|
||||
}
|
||||
|
||||
.current{
|
||||
margin-left: 20px;
|
||||
font-weight: 700;
|
||||
font-size: 25px;
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
animation-name: underlineAnimation;
|
||||
animation-duration: 10s;
|
||||
animation-iteration-count: infinite;
|
||||
text-shadow: 3px 4px 7px rgba(81, 67, 21, 0.8);
|
||||
}
|
||||
</style>
|
51
components/NewProject.vue
Normal file
51
components/NewProject.vue
Normal file
@ -0,0 +1,51 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Add Project</h1>
|
||||
<Input :keyup="function() { }" id="name" placeholder="Project Name" type="text"/>
|
||||
<Input :keyup="function() { }" id="desc" placeholder="Project Desc" type="text"/>
|
||||
<Input :keyup="function() { }" id="url" placeholder="Project URL" type="text"/>
|
||||
<Button :click="click">Post</Button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios';
|
||||
import Input from './Input.vue';
|
||||
import Button from './Button.vue';
|
||||
|
||||
export default {
|
||||
methods: {
|
||||
async click(e) {
|
||||
const name = document.getElementById("name").value
|
||||
const desc = document.getElementById("desc").value
|
||||
const url = document.getElementById("url").value
|
||||
const token = localStorage.getItem("token")
|
||||
const res = await axios.get(`/api/add_project?token=${token}&name=${name}&desc=${desc}&url=${url}`)
|
||||
if(res.data["error"]!==0)
|
||||
return alert("Error!")
|
||||
alert("Project added!")
|
||||
location.reload()
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
h1{
|
||||
color: var(--white);
|
||||
font-size: 50px;
|
||||
margin-bottom: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
div{
|
||||
background-color: var(--dark-three);
|
||||
padding: 50px;
|
||||
margin-top: 50px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
51
components/NewResource.vue
Normal file
51
components/NewResource.vue
Normal file
@ -0,0 +1,51 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Add Resource</h1>
|
||||
<Input :keyup="function(){}" id="name" placeholder="Resource Name" type="text"/>
|
||||
<Input :keyup="function(){}" id="tags" placeholder="Resource Tags (comma seperated)" type="text"/>
|
||||
<Input :keyup="function(){}" id="url" placeholder="Resource URL" type="text"/>
|
||||
<Button :click="click">Post</Button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Input from './Input.vue';
|
||||
import Button from './Button.vue';
|
||||
import axios from 'axios';
|
||||
|
||||
export default {
|
||||
methods: {
|
||||
async click(e) {
|
||||
const name = document.getElementById("name").value
|
||||
const tags = document.getElementById("tags").value
|
||||
const url = document.getElementById("url").value
|
||||
const token = localStorage.getItem("token")
|
||||
const res = await axios.get(`/api/add_resource?token=${token}&name=${name}&tags=${tags}&url=${url}`)
|
||||
if(res.data["error"]!==0)
|
||||
return alert("Error!")
|
||||
alert("Resource added!")
|
||||
location.reload()
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
h1{
|
||||
color: var(--white);
|
||||
font-size: 50px;
|
||||
margin-bottom: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
div{
|
||||
background-color: var(--dark-three);
|
||||
padding: 50px;
|
||||
margin-top: 50px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
63
components/Project.vue
Normal file
63
components/Project.vue
Normal file
@ -0,0 +1,63 @@
|
||||
<template>
|
||||
<main @click="redirect()">
|
||||
<i class='bx bx-code-alt'></i>
|
||||
<div>
|
||||
<h1>{{ name }}</h1>
|
||||
<h2>{{ desc }}</h2>
|
||||
</div>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ["name", "desc", "url"],
|
||||
methods: {
|
||||
redirect(e) {
|
||||
location.href = this.url
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
main {
|
||||
color: var(--white);
|
||||
background: var(--dark-two);
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 20px;
|
||||
padding: 40px;
|
||||
cursor: pointer;
|
||||
transition: .4s;
|
||||
height: 13%;
|
||||
width: 27%;
|
||||
}
|
||||
|
||||
main:hover{
|
||||
box-shadow: var(--def-shadow);
|
||||
}
|
||||
|
||||
i{
|
||||
font-size: 65px;
|
||||
animation-name: colorAnimation;
|
||||
animation-duration: 10s;
|
||||
animation-iteration-count: infinite;
|
||||
}
|
||||
|
||||
h1{
|
||||
font-size: 35px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
h2{
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1121px) {
|
||||
main{
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
</style>
|
28
components/ProjectList.vue
Normal file
28
components/ProjectList.vue
Normal file
@ -0,0 +1,28 @@
|
||||
<template>
|
||||
<div>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
div{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: 20px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 30px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1121px) {
|
||||
div {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
</style>
|
66
components/Resource.vue
Normal file
66
components/Resource.vue
Normal file
@ -0,0 +1,66 @@
|
||||
<template>
|
||||
<main @click="redirect()" class="mn">
|
||||
<div class="resource">
|
||||
<h1>{{ name }}</h1>
|
||||
<div class="tags">
|
||||
<Tag v-for="tag in tags" :key="tag">{{ tag }}</Tag>
|
||||
</div>
|
||||
</div>
|
||||
<i class='bx bx-right-arrow-alt' ></i>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Tag from './Tag.vue';
|
||||
|
||||
export default {
|
||||
props: ["tags", "name", "url"],
|
||||
methods: {
|
||||
redirect(e){
|
||||
location.href = this.url
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
main{
|
||||
background: var(--dark-two);
|
||||
padding: 30px 40px 30px 40px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
color: var(--white);
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
transition: .4s;
|
||||
width: 80%;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
main:hover{
|
||||
box-shadow: var(--def-shadow);
|
||||
}
|
||||
|
||||
.mn:hover i{
|
||||
color: white;
|
||||
}
|
||||
|
||||
.resource{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.tags{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
i{
|
||||
font-size: 70px;
|
||||
cursor: pointer;
|
||||
color: var(--dark-two);
|
||||
transition: .4s;
|
||||
}
|
||||
</style>
|
24
components/Tag.vue
Normal file
24
components/Tag.vue
Normal file
@ -0,0 +1,24 @@
|
||||
<template>
|
||||
<p>
|
||||
#<slot></slot>
|
||||
</p>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
p{
|
||||
background: var(--dark-three);
|
||||
color: white;
|
||||
text-shadow: 1px 1px 2px white;
|
||||
padding: 5px 10px 5px 10px;
|
||||
font-size: 25px;
|
||||
border-radius: 7px;
|
||||
margin-top: 10px;
|
||||
transition: .4s;
|
||||
}
|
||||
</style>
|
31
nuxt.config.js
Normal file
31
nuxt.config.js
Normal file
@ -0,0 +1,31 @@
|
||||
export default {
|
||||
head: {
|
||||
title: "[ngn]",
|
||||
htmlAttrs: {
|
||||
lang: "en",
|
||||
},
|
||||
meta: [
|
||||
{ charset: "utf-8" },
|
||||
{ name: "viewport", content: "width=device-width, initial-scale=1" },
|
||||
{ hid: "description", name: "description", content: "" },
|
||||
{ name: "format-detection", content: "telephone=no" },
|
||||
{ hid: "og:title", content: "[ngn]" },
|
||||
{ hid: "og:description", content: "ngn's (very cool) personal website" },
|
||||
{ hid: "og:url", content: "https://ngn13.fun" },
|
||||
{ name: "theme-color", content: "#0c16d1", "data-react-helmet":"true"},
|
||||
],
|
||||
link: [{ rel: "stylesheet", href: "https://unpkg.com/boxicons@2.1.4/css/boxicons.min.css" }]
|
||||
},
|
||||
css: ["@/static/global.css"],
|
||||
plugins: [],
|
||||
components: true,
|
||||
buildModules: [],
|
||||
modules: ["@nuxtjs/axios"],
|
||||
axios: {
|
||||
baseURL: "/",
|
||||
},
|
||||
build: {},
|
||||
serverMiddleware: {
|
||||
"/api": "~/api",
|
||||
},
|
||||
};
|
25913
package-lock.json
generated
Normal file
25913
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
20
package.json
Normal file
20
package.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "my-website",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "nuxt",
|
||||
"build": "nuxt build",
|
||||
"start": "nuxt start",
|
||||
"generate": "nuxt generate"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nuxtjs/axios": "^5.13.6",
|
||||
"core-js": "^3.25.3",
|
||||
"express": "^4.18.2",
|
||||
"nuxt": "^2.15.8",
|
||||
"vue": "^2.7.10",
|
||||
"vue-server-renderer": "^2.7.10",
|
||||
"vue-template-compiler": "^2.7.10"
|
||||
}
|
||||
}
|
86
pages/index.vue
Normal file
86
pages/index.vue
Normal file
@ -0,0 +1,86 @@
|
||||
<template>
|
||||
<div>
|
||||
<Navbar />
|
||||
<Header>
|
||||
<glitch>echo</glitch> hello world!
|
||||
</Header>
|
||||
<div class="info">
|
||||
<Card>
|
||||
<h1>👋 Welcome to my website!</h1>
|
||||
<h2>
|
||||
I am a high school student who is interested in
|
||||
<br>
|
||||
• cyber security
|
||||
<br>
|
||||
• coding
|
||||
<br>
|
||||
• electronics
|
||||
<br>
|
||||
• simply: everything about computers!
|
||||
</h2>
|
||||
</Card>
|
||||
<Card>
|
||||
<h1>👉 Checkout my socials</h1>
|
||||
<h2>Here you can find my socials for following platforms:</h2>
|
||||
<br>
|
||||
<a href="https://discord.com/users/568131907368386565"><i class='bx bxl-discord-alt'></i> Discord</a>
|
||||
<br>
|
||||
<a href="https://github.com/ngn13"><i class='bx bxl-github'></i> Github</a>
|
||||
<br>
|
||||
<a href="https://www.reddit.com/user/_ngn"><i class='bx bxl-reddit'></i> Reddit</a>
|
||||
<br>
|
||||
<a href="https://fosstodon.org/@ngn"><i class='bx bxl-mastodon'></i> Fosstodon</a>
|
||||
</Card>
|
||||
</div>
|
||||
<Logout v-if="logged"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Navbar from "../components/Navbar.vue";
|
||||
import Header from "../components/Header.vue";
|
||||
import Card from "../components/Card.vue"
|
||||
import Logout from "../components/Logout.vue";
|
||||
|
||||
export default {
|
||||
head() {
|
||||
return {
|
||||
title: "[ngn]",
|
||||
meta: [
|
||||
{
|
||||
hid: "description",
|
||||
name: "description",
|
||||
content: "ngn's Personal Website | Home Page"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
logged: false
|
||||
}
|
||||
},
|
||||
mounted(){
|
||||
if(localStorage.getItem("token"))
|
||||
this.logged = true
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.info {
|
||||
padding: 50px;
|
||||
gap: 30px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
|
||||
@media only screen and (max-width: 1076px) {
|
||||
.info {
|
||||
flex-direction: column;
|
||||
}
|
||||
.info div {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
</style>
|
51
pages/login.vue
Normal file
51
pages/login.vue
Normal file
@ -0,0 +1,51 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Login Page</h1>
|
||||
<Input :keyup="function() { }" placeholder="Password" type="password" id="pass"/>
|
||||
<Button :click="click">Login</Button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Input from '../components/Input.vue';
|
||||
import Button from '../components/Button.vue';
|
||||
import axios from "axios";
|
||||
|
||||
export default {
|
||||
methods: {
|
||||
async click(e) {
|
||||
const pass = document.getElementById("pass").value
|
||||
const res = await axios.get(`/api/login?pass=${pass}`)
|
||||
if(res.data["error"]===0){
|
||||
localStorage.setItem("token", res.data["token"])
|
||||
return location.href="/"
|
||||
}
|
||||
alert("Incorrect password!")
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
div {
|
||||
padding: 50px;
|
||||
background: var(--dark-three);
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
margin: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
color: var(--white);
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
h1{
|
||||
font-size: 70px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
</style>
|
73
pages/projects.vue
Normal file
73
pages/projects.vue
Normal file
@ -0,0 +1,73 @@
|
||||
<template>
|
||||
<div>
|
||||
<Navbar />
|
||||
<Header>
|
||||
<glitch>ls -la</glitch> projects
|
||||
</Header>
|
||||
<div class="projects">
|
||||
<ProjectList v-for="project in projects" :key="project">
|
||||
<Project v-for="p in project" :key="p" :name="p.name" :desc="p.desc" :url="p.url"/>
|
||||
</ProjectList>
|
||||
</div>
|
||||
<NewProject v-if="logged"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ProjectList from "../components/ProjectList.vue";
|
||||
import Project from "../components/Project.vue";
|
||||
import NewProject from "../components/NewProject.vue";
|
||||
import axios from "axios";
|
||||
|
||||
export default {
|
||||
head() {
|
||||
return {
|
||||
title: "[ngn]",
|
||||
meta: [
|
||||
{
|
||||
hid: "description",
|
||||
name: "description",
|
||||
content: "ngn's Personal Website | Projects Page"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
logged: false,
|
||||
projects: []
|
||||
}
|
||||
},
|
||||
mounted: async function(){
|
||||
if(localStorage.getItem("token"))
|
||||
this.logged = true
|
||||
|
||||
const res = await axios.get("/api/get_projects")
|
||||
|
||||
let all = res.data["projects"]
|
||||
let projects = []
|
||||
let project = []
|
||||
for(let i = 0; i<all.length; i++){
|
||||
if(project.length!==3)
|
||||
project.push(all[i])
|
||||
else{
|
||||
projects.push(project)
|
||||
project = []
|
||||
}
|
||||
|
||||
if(i===all.length-1){
|
||||
projects.push(project)
|
||||
}
|
||||
}
|
||||
this.projects = projects
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.projects{
|
||||
margin-top: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
</style>
|
76
pages/resources.vue
Normal file
76
pages/resources.vue
Normal file
@ -0,0 +1,76 @@
|
||||
<template>
|
||||
<main>
|
||||
<Navbar />
|
||||
<Header>
|
||||
<glitch>cat</glitch> {{ header }}
|
||||
</Header>
|
||||
<div class="resources">
|
||||
<Input :keyup="keyup" placeholder="Search resource" type="text"/>
|
||||
<Resource v-for="resource in resources" :key="resource" :name="resource.name" :tags="resource.tags" :url="resource.url" />
|
||||
</div>
|
||||
<NewResource v-if="logged"/>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios';
|
||||
import Resource from '../components/Resource.vue';
|
||||
import Input from '../components/Input.vue';
|
||||
import NewResource from '../components/NewResource.vue';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
header: "resources",
|
||||
logged: false,
|
||||
resources: [],
|
||||
all: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
keyup(e) {
|
||||
let val = e.target.value
|
||||
if(e.key==="Backspace" && val===""){
|
||||
this.header = "resources"
|
||||
this.resources = this.all
|
||||
return
|
||||
}
|
||||
if(e.key==="OS")
|
||||
return
|
||||
this.header = `resources | grep ${val}`
|
||||
|
||||
// dirty asf search alg
|
||||
this.resources = []
|
||||
for(let i = 0; i < this.all.length; i++){
|
||||
if(this.all[i].name.toLowerCase().includes(val.toLowerCase()))
|
||||
this.resources.push(this.all[i])
|
||||
|
||||
for(let e = 0; e < this.all[i].tags.length; e++){
|
||||
if(this.all[i].tags[e].toLowerCase().includes(val.toLowerCase())){
|
||||
if(this.resources.indexOf(this.all[i])===-1)
|
||||
this.resources.push(this.all[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted: async function(){
|
||||
if(localStorage.getItem("token"))
|
||||
this.logged = true
|
||||
|
||||
const res = await axios.get("/api/get_resources")
|
||||
this.resources = res.data["resources"]
|
||||
this.all = res.data["resources"]
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.resources {
|
||||
padding: 50px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 40px
|
||||
}
|
||||
</style>
|
BIN
static/Minecraft.ttf
Normal file
BIN
static/Minecraft.ttf
Normal file
Binary file not shown.
315
static/global.css
Normal file
315
static/global.css
Normal file
@ -0,0 +1,315 @@
|
||||
@import url("https://fonts.googleapis.com/css2?family=Ubuntu:wght@300&display=swap");
|
||||
|
||||
:root {
|
||||
--white: white;
|
||||
--dark-one: #141414;
|
||||
--dark-two: #18191a;
|
||||
--dark-three: #282828;
|
||||
--dark-four: #242526;
|
||||
--dark-fife: #3a3b3c;
|
||||
--border-rad: 30px;
|
||||
--def-shadow: rgba(0, 0, 0, 0.25) 0px 54px 55px,
|
||||
rgba(0, 0, 0, 0.12) 0px -12px 30px, rgba(0, 0, 0, 0.12) 0px 4px 6px,
|
||||
rgba(0, 0, 0, 0.17) 0px 12px 13px, rgba(0, 0, 0, 0.09) 0px -3px 5px;
|
||||
}
|
||||
|
||||
* {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
background: #141414;
|
||||
font-family: "Ubuntu", sans-serif;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
border-radius: 10px;
|
||||
width: 10px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
border-radius: 10px;
|
||||
background: #181818;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
border-radius: 10px;
|
||||
background: #282828;
|
||||
}
|
||||
|
||||
@keyframes colorAnimation {
|
||||
100%,
|
||||
0% {
|
||||
color: rgb(255, 0, 0);
|
||||
}
|
||||
8% {
|
||||
color: rgb(255, 127, 0);
|
||||
}
|
||||
16% {
|
||||
color: rgb(255, 255, 0);
|
||||
}
|
||||
25% {
|
||||
color: rgb(127, 255, 0);
|
||||
}
|
||||
33% {
|
||||
color: rgb(0, 255, 0);
|
||||
}
|
||||
41% {
|
||||
color: rgb(0, 255, 127);
|
||||
}
|
||||
50% {
|
||||
color: rgb(0, 255, 255);
|
||||
}
|
||||
58% {
|
||||
color: rgb(0, 127, 255);
|
||||
}
|
||||
66% {
|
||||
color: rgb(0, 0, 255);
|
||||
}
|
||||
75% {
|
||||
color: rgb(127, 0, 255);
|
||||
}
|
||||
83% {
|
||||
color: rgb(255, 0, 255);
|
||||
}
|
||||
91% {
|
||||
color: rgb(255, 0, 127);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes borderAnimation {
|
||||
100%,
|
||||
0% {
|
||||
border-bottom-color: rgb(255, 0, 0);
|
||||
}
|
||||
8% {
|
||||
border-bottom-color: rgb(255, 127, 0);
|
||||
}
|
||||
16% {
|
||||
border-bottom-color: rgb(255, 255, 0);
|
||||
}
|
||||
25% {
|
||||
border-bottom-color: rgb(127, 255, 0);
|
||||
}
|
||||
33% {
|
||||
border-bottom-color: rgb(0, 255, 0);
|
||||
}
|
||||
41% {
|
||||
border-bottom-color: rgb(0, 255, 127);
|
||||
}
|
||||
50% {
|
||||
border-bottom-color: rgb(0, 255, 255);
|
||||
}
|
||||
58% {
|
||||
border-bottom-color: rgb(0, 127, 255);
|
||||
}
|
||||
66% {
|
||||
border-bottom-color: rgb(0, 0, 255);
|
||||
}
|
||||
75% {
|
||||
border-bottom-color: rgb(127, 0, 255);
|
||||
}
|
||||
83% {
|
||||
border-bottom-color: rgb(255, 0, 255);
|
||||
}
|
||||
91% {
|
||||
border-bottom-color: rgb(255, 0, 127);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fullBorderAnimation {
|
||||
100%,
|
||||
0% {
|
||||
border-color: rgb(255, 0, 0);
|
||||
}
|
||||
8% {
|
||||
border-color: rgb(255, 127, 0);
|
||||
}
|
||||
16% {
|
||||
border-color: rgb(255, 255, 0);
|
||||
}
|
||||
25% {
|
||||
border-color: rgb(127, 255, 0);
|
||||
}
|
||||
33% {
|
||||
border-color: rgb(0, 255, 0);
|
||||
}
|
||||
41% {
|
||||
border-color: rgb(0, 255, 127);
|
||||
}
|
||||
50% {
|
||||
border-color: rgb(0, 255, 255);
|
||||
}
|
||||
58% {
|
||||
border-color: rgb(0, 127, 255);
|
||||
}
|
||||
66% {
|
||||
border-color: rgb(0, 0, 255);
|
||||
}
|
||||
75% {
|
||||
border-color: rgb(127, 0, 255);
|
||||
}
|
||||
83% {
|
||||
border-color: rgb(255, 0, 255);
|
||||
}
|
||||
91% {
|
||||
border-color: rgb(255, 0, 127);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes gayShadowAnimation {
|
||||
100%,
|
||||
0% {
|
||||
box-shadow: rgba(255, 0, 0, 0.07) 0px 1px 2px,
|
||||
rgba(255, 0, 0, 0.07) 0px 2px 4px, rgba(255, 0, 0, 0.07) 0px 4px 8px,
|
||||
rgba(255, 0, 0, 0.07) 0px 8px 16px, rgba(255, 0, 0, 0.07) 0px 16px 32px,
|
||||
rgba(255, 0, 0, 0.07) 0px 32px 64px;
|
||||
}
|
||||
8% {
|
||||
box-shadow: rgba(255, 127, 0, 0.07) 0px 1px 2px,
|
||||
rgba(255, 127, 0, 0.07) 0px 2px 4px, rgba(255, 127, 0, 0.07) 0px 4px 8px,
|
||||
rgba(255, 127, 0, 0.07) 0px 8px 16px,
|
||||
rgba(255, 127, 0, 0.07) 0px 16px 32px,
|
||||
rgba(255, 127, 0, 0.07) 0px 32px 64px;
|
||||
}
|
||||
16% {
|
||||
box-shadow: rgba(255, 255, 0, 0.07) 0px 1px 2px,
|
||||
rgba(255, 255, 0, 0.07) 0px 2px 4px, rgba(255, 255, 0, 0.07) 0px 4px 8px,
|
||||
rgba(255, 255, 0, 0.07) 0px 8px 16px,
|
||||
rgba(255, 255, 0, 0.07) 0px 16px 32px,
|
||||
rgba(255, 255, 0, 0.07) 0px 32px 64px;
|
||||
}
|
||||
25% {
|
||||
box-shadow: rgba(127, 255, 0, 0.07) 0px 1px 2px,
|
||||
rgba(127, 255, 0, 0.07) 0px 2px 4px, rgba(127, 255, 0, 0.07) 0px 4px 8px,
|
||||
rgba(127, 255, 0, 0.07) 0px 8px 16px,
|
||||
rgba(127, 255, 0, 0.07) 0px 16px 32px,
|
||||
rgba(127, 255, 0, 0.07) 0px 32px 64px;
|
||||
}
|
||||
33% {
|
||||
box-shadow: rgba(0, 255, 0, 0.07) 0px 1px 2px,
|
||||
rgba(0, 255, 0, 0.07) 0px 2px 4px, rgba(0, 255, 0, 0.07) 0px 4px 8px,
|
||||
rgba(0, 255, 0, 0.07) 0px 8px 16px, rgba(0, 255, 0, 0.07) 0px 16px 32px,
|
||||
rgba(0, 255, 0, 0.07) 0px 32px 64px;
|
||||
}
|
||||
41% {
|
||||
box-shadow: rgba(0, 255, 127, 0.07) 0px 1px 2px,
|
||||
rgba(0, 255, 127, 0.07) 0px 2px 4px, rgba(0, 255, 127, 0.07) 0px 4px 8px,
|
||||
rgba(0, 255, 127, 0.07) 0px 8px 16px,
|
||||
rgba(0, 255, 127, 0.07) 0px 16px 32px,
|
||||
rgba(0, 255, 127, 0.07) 0px 32px 64px;
|
||||
}
|
||||
50% {
|
||||
box-shadow: rgba(0, 255, 255, 0.07) 0px 1px 2px,
|
||||
rgba(0, 255, 255, 0.07) 0px 2px 4px, rgba(0, 255, 255, 0.07) 0px 4px 8px,
|
||||
rgba(0, 255, 255, 0.07) 0px 8px 16px,
|
||||
rgba(0, 255, 255, 0.07) 0px 16px 32px,
|
||||
rgba(0, 255, 255, 0.07) 0px 32px 64px;
|
||||
}
|
||||
58% {
|
||||
box-shadow: rgba(0, 127, 255, 0.07) 0px 1px 2px,
|
||||
rgba(0, 127, 255, 0.07) 0px 2px 4px, rgba(0, 127, 255, 0.07) 0px 4px 8px,
|
||||
rgba(0, 127, 255, 0.07) 0px 8px 16px,
|
||||
rgba(0, 127, 255, 0.07) 0px 16px 32px,
|
||||
rgba(0, 127, 255, 0.07) 0px 32px 64px;
|
||||
}
|
||||
66% {
|
||||
box-shadow: rgba(0, 0, 255, 0.07) 0px 1px 2px,
|
||||
rgba(0, 0, 255, 0.07) 0px 2px 4px, rgba(0, 0, 255, 0.07) 0px 4px 8px,
|
||||
rgba(0, 0, 255, 0.07) 0px 8px 16px, rgba(0, 0, 255, 0.07) 0px 16px 32px,
|
||||
rgba(0, 0, 255, 0.07) 0px 32px 64px;
|
||||
}
|
||||
75% {
|
||||
box-shadow: rgba(127, 0, 255, 0.07) 0px 1px 2px,
|
||||
rgba(127, 0, 255, 0.07) 0px 2px 4px, rgba(127, 0, 255, 0.07) 0px 4px 8px,
|
||||
rgba(127, 0, 255, 0.07) 0px 8px 16px,
|
||||
rgba(127, 0, 255, 0.07) 0px 16px 32px,
|
||||
rgba(127, 0, 255, 0.07) 0px 32px 64px;
|
||||
}
|
||||
83% {
|
||||
box-shadow: rgba(255, 0, 255, 0.07) 0px 1px 2px,
|
||||
rgba(255, 0, 255, 0.07) 0px 2px 4px, rgba(255, 0, 255, 0.07) 0px 4px 8px,
|
||||
rgba(255, 0, 255, 0.07) 0px 8px 16px,
|
||||
rgba(255, 0, 255, 0.07) 0px 16px 32px,
|
||||
rgba(255, 0, 255, 0.07) 0px 32px 64px;
|
||||
}
|
||||
91% {
|
||||
box-shadow: rgba(255, 0, 127, 0.07) 0px 1px 2px,
|
||||
rgba(255, 0, 127, 0.07) 0px 2px 4px, rgba(255, 0, 127, 0.07) 0px 4px 8px,
|
||||
rgba(255, 0, 127, 0.07) 0px 8px 16px,
|
||||
rgba(255, 0, 127, 0.07) 0px 16px 32px,
|
||||
rgba(255, 0, 127, 0.07) 0px 32px 64px;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes underlineAnimation {
|
||||
100%,
|
||||
0% {
|
||||
text-decoration-color: rgb(255, 0, 0);
|
||||
}
|
||||
8% {
|
||||
text-decoration-color: rgb(255, 127, 0);
|
||||
}
|
||||
16% {
|
||||
text-decoration-color: rgb(255, 255, 0);
|
||||
}
|
||||
25% {
|
||||
text-decoration-color: rgb(127, 255, 0);
|
||||
}
|
||||
33% {
|
||||
text-decoration-color: rgb(0, 255, 0);
|
||||
}
|
||||
41% {
|
||||
text-decoration-color: rgb(0, 255, 127);
|
||||
}
|
||||
50% {
|
||||
text-decoration-color: rgb(0, 255, 255);
|
||||
}
|
||||
58% {
|
||||
text-decoration-color: rgb(0, 127, 255);
|
||||
}
|
||||
66% {
|
||||
text-decoration-color: rgb(0, 0, 255);
|
||||
}
|
||||
75% {
|
||||
text-decoration-color: rgb(127, 0, 255);
|
||||
}
|
||||
83% {
|
||||
text-decoration-color: rgb(255, 0, 255);
|
||||
}
|
||||
91% {
|
||||
text-decoration-color: rgb(255, 0, 127);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes minecraftAnimation {
|
||||
0%{
|
||||
font-size: 15px;
|
||||
}
|
||||
50%{
|
||||
font-size: 17px;
|
||||
}
|
||||
100%{
|
||||
font-size: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Minecraft";
|
||||
src: url("/Minecraft.ttf") format("opentype");
|
||||
}
|
||||
|
||||
glitch {
|
||||
animation-name: colorAnimation;
|
||||
animation-iteration-count: infinite;
|
||||
animation-duration: 10s;
|
||||
text-shadow: none;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user