Beta version

This commit is contained in:
Andrew Illarionov 2023-11-18 20:28:27 +03:00
parent ff9cdcab1d
commit f16d54aa46
28 changed files with 16368 additions and 121 deletions

14
app.vue
View File

@ -1,11 +1,19 @@
<script setup lang="ts"></script>
<script setup lang="ts">
useHead({
titleTemplate: (chunk) => {
return !chunk || chunk === 'Enderman' ? 'Enderman' : `${chunk} Enderman`
},
})
</script>
<template>
<div
id="ender-layout"
class="d-flex flex-column justify-content-center align-items-center h-100"
class="d-flex flex-column align-items-center pt-sm-5 h-100"
>
<Card />
<Transition name="page">
<Card />
</Transition>
</div>
<Portal

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -2,14 +2,25 @@
@import '@fontsource/Lato/index.css';
@import '@fontsource/Alexandria/700.css';
$grid-breakpoints: (
xs: 0,
sm: 601px,
md: 996px,
lg: 1281px,
xl: 1921px,
xxl: 2561px
);
// Bootstrap & animations.
@import 'bootstrap/dist/css/bootstrap.css';
@import 'transition.scss';
@import 'animate.css';
@import '../../node_modules/bootstrap/scss/bootstrap';
@import '../../node_modules/animate.css/animate';
@import 'transitions';
// CSS Variables.
:root {
--animate-duration: 1s;
--animate-delay: 0.75s;
--animate-repeat: 1;
}
// The HTML page.
@ -49,6 +60,10 @@ body {
color: inherit;
}
.list-style-type-none {
list-style-type: none;
}
.text-align-center {
text-align: center;
}
@ -57,17 +72,45 @@ body {
font-size: 14px;
}
.grid-cols-3 {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.display-xs-none {
display: none;
}
.alex {
font-family: 'Alexandria', sans-serif;
}
// Query-overridable classes.
.enderesque {
.background {
background-color: rgba(0, 0, 0, 0.5);
}
.dimensions {
width: 100%;
height: 100%;
}
.link {
color: inherit;
}
text-decoration: none;
transition: 0.3s ease;
.link:hover {
color: cornflowerblue;
&:hover {
color: cornflowerblue;
}
&-hi {
@extend .link;
color: cornflowerblue;
&:hover {
color: royalblue;
}
}
}
.radial-gradient {
@ -79,17 +122,79 @@ body {
);
}
@media (prefers-color-scheme: dark) {
@property --scrollbar {
syntax: '<color>';
inherits: true;
initial-value: rgba(255, 255, 255, 0.15);
}
.scrollbar {
min-height: 128px;
transition: --scrollbar 0.15s ease;
scrollbar-gutter: stable;
scrollbar-width: thin;
scrollbar-color: rgba(255, 255, 255, 0.15) rgba(0, 0, 0, 0.3);
&:hover {
scrollbar-color: rgba(255, 255, 255, 0.3) rgba(0, 0, 0, 0.3);
--scrollbar: rgba(255, 255, 255, 0.3);
}
&::-webkit-scrollbar {
width: 8px;
}
&::-webkit-scrollbar-track {
border-radius: 8px;
background-color: rgba(0, 0, 0, 0.3);
}
&::-webkit-scrollbar-thumb {
border-radius: 8px;
background-color: var(--scrollbar);
}
}
.fade-mask {
mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 0), rgba(0, 0, 0, 1) 5%, rgba(0, 0, 0, 1) 95%, rgba(0, 0, 0, 0));
}
@media (prefers-color-scheme: light) {
body {
color: black;
}
.enderesque {
.scrollbar {
scrollbar-color: rgba(0, 0, 0, 0.15) rgba(255, 255, 255, 0.3);
&:hover {
scrollbar-color: rgba(0, 0, 0, 0.3) rgba(255, 255, 255, 0.3);
--scrollbar: rgba(0, 0, 0, 0.3);
}
&::-webkit-scrollbar-track {
background-color: rgba(255, 255, 255, 0.3);
}
}
.background {
background-color: rgba(255, 255, 255, 0.75);
}
.link:hover {
color: darkslateblue;
.link {
&:hover {
color: royalblue;
}
&-hi {
color: royalblue;
&:hover {
color: darkblue;
}
}
}
.radial-gradient {
@ -102,43 +207,57 @@ body {
}
}
// Dimensions.
@media (max-width: 575px) {
.enderesque {
width: 100%;
}
}
@media (min-width: 576px) {
.enderesque {
// Dynamic classes.
@include media-breakpoint-up(sm) {
.dimensions {
width: 80%;
height: auto;
max-height: 90%;
}
.rounded-card {
border-radius: 1em;
}
.display-xs-none {
display: block;
}
.animate__animated-sm {
-webkit-animation-duration: 1s;
animation-duration: 1s;
-webkit-animation-duration: var(--animate-duration);
animation-duration: var(--animate-duration);
-webkit-animation-fill-mode: both;
animation-fill-mode: both;
}
.animate__delay-1-5s {
-webkit-animation-delay: 1s;
animation-delay: 1s;
-webkit-animation-delay: calc(var(--animate-delay) * 1.5);
animation-delay: calc(var(--animate-delay) * 1.5);
}
}
@media (min-width: 768px) {
.enderesque {
@include media-breakpoint-up(md) {
}
@include media-breakpoint-up(lg) {
.dimensions {
width: 60%;
}
}
@media (min-width: 992px) {
.enderesque {
width: 60%;
}
}
@media (min-width: 1200px) {
.enderesque {
width: 60%;
}
}
@media (min-width: 2000px) {
.enderesque {
@include media-breakpoint-up(xl) {
.dimensions {
width: 40%;
}
}
@include media-breakpoint-up(xxl) {
.dimensions {
width: 30%;
}
}

View File

@ -0,0 +1,14 @@
body::-webkit-scrollbar {
width: 1em;
}
body::-webkit-scrollbar-track {
-webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
}
body::-webkit-scrollbar-thumb {
background-color: darkgrey;
outline: 1px solid slategrey;
}
/*# sourceMappingURL=scrollbar.css.map */

View File

@ -0,0 +1 @@
{"version":3,"sourceRoot":"","sources":["scrollbar.scss"],"names":[],"mappings":"AAAA;EACI;;;AAGJ;EACI;;;AAGJ;EACE;EACA","file":"scrollbar.css"}

View File

@ -1 +0,0 @@
{"version":3,"sourceRoot":"","sources":["transition.scss"],"names":[],"mappings":"AACE;EAEE;;AAGF;EAEE;EACA","file":"transition.css"}

View File

@ -6,4 +6,4 @@
filter: blur(1rem);
}
/*# sourceMappingURL=transition.css.map */
/*# sourceMappingURL=transitions.css.map */

View File

@ -0,0 +1 @@
{"version":3,"sourceRoot":"","sources":["transitions.scss"],"names":[],"mappings":"AACE;EAEE;;AAGF;EAEE;EACA","file":"transitions.css"}

View File

@ -7,6 +7,6 @@
&-enter-from,
&-leave-to {
opacity: 0;
filter: blur(1rem);
filter: blur(1em);
}
}

View File

@ -2,11 +2,12 @@
<template>
<main
class="enderesque d-flex flex-column rounded-card gap-2 p-4 animate__animated animate__fadeInDown animate__delay-1s"
class="dimensions scrollbar background overflow-auto d-flex flex-column rounded-card gap-2 p-4 animate__animated-sm animate__delay-1-5s animate__fadeInDown"
>
<Navigation />
<h3>Welcome!</h3>
<NuxtPage class="ender-card-body" />
<NuxtPage
class="scrollbar overflow-y-auto mb-3 mb-sm-0 py-4 pe-3 fade-mask"
/>
</main>
</template>

View File

@ -4,7 +4,7 @@ const currentYear = new Date().getFullYear()
<template>
<footer
class="float user-select-none mb-2 animate__animated animate__fadeInUpBig animate__slow text-align-center line-height-1-5"
class="float user-select-none mb-2 animate__animated animate__delay-1s animate__fadeInUpBig animate__slow text-align-center line-height-1-5"
>
<span class="transpaque font-small text-shadow">
© 2018-{{ currentYear }}, <a href="https://enderman.ch">Enderman</a>. All

43
components/EMail.vue Normal file
View File

@ -0,0 +1,43 @@
<script setup lang="ts">
const props = defineProps({
address: {
type: String,
required: true,
},
subject: {
type: String,
default: '',
},
body: {
type: String,
default: '',
},
cc: {
type: String,
default: '',
},
bcc: {
type: String,
default: '',
},
})
const href =
`mailto:${props.address}` +
(props.body ? `&body=${props.body}` : '') +
(props.subject ? `${props.body ? '&' : '?'}subject=${props.subject}` : '') +
(props.cc ? `${props.body || props.subject ? '&' : '?'}cc=${props.cc}` : '') +
(props.bcc
? `${props.body || props.subject || props.cc ? '&' : '?'}bcc=${props.bcc}`
: '')
</script>
<template>
<a class="link-hi" target="_blank" rel="noopener" :href="href">
<slot>
{{ props.address }}
</slot>
</a>
</template>
<style scoped lang="scss"></style>

View File

@ -22,8 +22,8 @@ const props = defineProps({
<template>
<NuxtLink
class="icon link d-flex flex-row align-items-center gap-2 user-select-none no-decoration"
active-class="icon-active px-3"
class="link d-flex flex-row align-items-center gap-2 user-select-none no-decoration"
active-class="icon-active px-sm-3"
:to="!props.external ? props.path : undefined"
:href="props.external ? props.path : undefined"
>
@ -33,14 +33,16 @@ const props = defineProps({
:src="props.icon"
:alt="props.alt"
/>
<strong>{{ props.name }}</strong>
<span class="display-xs-none">
<strong>
{{ props.name }}
</strong>
</span>
</NuxtLink>
</template>
<style scoped lang="scss">
.icon {
transition: 0.3s ease;
&-active {
transform: translate(2px, 2px) rotate3d(1, 1, 1, 5deg) scale(1.25);
}

View File

@ -41,7 +41,7 @@ const props = defineProps({
:alt="props.alt"
/>
<div>
<h1 class="phat mb-0">{{ props.title }}</h1>
<h1 class="alex mb-0">{{ props.title }}</h1>
<Separator />
<p class="mb-0">{{ props.description }}</p>
</div>
@ -50,10 +50,6 @@ const props = defineProps({
</template>
<style scoped lang="scss">
.phat {
font-family: 'Alexandria', sans-serif;
}
.logo {
> img.logo-image {
transition: ease 0.3s;

View File

@ -15,7 +15,7 @@ const icons = [aboutIcon, projectIcon, socialIcon]
<template>
<nav
class="d-flex flex-column flex-lg-row justify-content-lg-between gap-sm-2 gap-lg-3"
class="d-flex flex-row flex-wrap flex-sm-column flex-lg-row justify-content-around justify-content-sm-start justify-content-lg-between gap-2 gap-lg-3"
>
<Logo
:src="logo"
@ -24,7 +24,7 @@ const icons = [aboutIcon, projectIcon, socialIcon]
description="official website"
/>
<ul
class="navbar-nav flex-sm-row align-items-lg-center justify-content-sm-center gap-sm-3 mx-2"
class="navbar-nav flex-row align-items-center align-items-sm-start align-items-lg-center justify-content-center gap-3 m-2 m-sm-0 mx-lg-2 my-sm-2 my-lg-0"
>
<li v-for="(page, index) in pages" :key="index" class="nav-item">
<LinkButton

View File

@ -1,4 +1,9 @@
<script setup lang="ts">
import sky from '~/assets/images/portal/sky.png'
import particles from '~/assets/images/portal/particles.png'
const resources: string[] = [sky, particles]
const props = defineProps({
layout: {
default: '#ender-app',
@ -79,8 +84,8 @@ class Canvas {
}
fill() {
this.element.width = window.innerWidth
this.element.height = window.innerHeight
this.element.width = window.innerWidth * window.devicePixelRatio
this.element.height = window.innerHeight * window.devicePixelRatio
}
full(): boolean {
@ -235,7 +240,7 @@ class Portal {
if (directory.at(-1) !== '/') directory += '/'
// Images to load.
const images = [`${directory}sky.png`, `${directory}particles.png`]
const images = resources // [`${directory}sky.png`, `${directory}particles.png`]
// Notice.
this.notice()
@ -498,7 +503,7 @@ class Portal {
if (this.animate) {
// Speed up the animation if the user has clicked.
if (this.clickTime !== null) {
if (this.clickTime !== 0) {
this.speed =
this.dv * this.initialSpeed -
Math.min(

View File

@ -2,7 +2,6 @@
export default defineNuxtConfig({
app: {
head: {
titleTemplate: '%s Enderman',
htmlAttrs: {
lang: 'en',
},
@ -49,7 +48,11 @@ export default defineNuxtConfig({
'@nuxt/content',
'@nuxtjs/eslint-module',
'@pinia/nuxt',
'nuxt-quasar-ui',
],
quasar: {
lang: 'en-US',
},
typescript: {
typeCheck: true,
},

210
package-lock.json generated
View File

@ -17,10 +17,12 @@
"@fortawesome/free-regular-svg-icons": "^6.4.2",
"@fortawesome/free-solid-svg-icons": "^6.4.2",
"@fortawesome/vue-fontawesome": "^3.0.5",
"@quasar/extras": "^1.16.8",
"animate.css": "^4.1.1",
"bootstrap": "^5.3.2",
"humps": "^2.0.1",
"pinia": "^2.1.7"
"pinia": "^2.1.7",
"quasar": "^2.14.0"
},
"devDependencies": {
"@nuxt/content": "^2.9.0",
@ -36,6 +38,7 @@
"eslint-plugin-prettier": "^5.0.1",
"nuxt": "^3.8.1",
"nuxt-font-loader": "^2.3.4",
"nuxt-quasar-ui": "^2.0.6",
"prettier": "^3.0.3",
"sass": "^1.69.5",
"typescript": "^5.2.2",
@ -2735,6 +2738,15 @@
"url": "https://opencollective.com/popperjs"
}
},
"node_modules/@quasar/extras": {
"version": "1.16.8",
"resolved": "https://registry.npmjs.org/@quasar/extras/-/extras-1.16.8.tgz",
"integrity": "sha512-mNSwQ6wkIVoAemhYdLm9q/FVqLHmVONZgCYdLLeqpakKNsR0r/zHQnCngzdDaXI7veYEvE0uW1gJa1wdQsxXxA==",
"funding": {
"type": "github",
"url": "https://donate.quasar.dev"
}
},
"node_modules/@rollup/plugin-alias": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/@rollup/plugin-alias/-/plugin-alias-5.0.1.tgz",
@ -4920,6 +4932,19 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/assert": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/assert/-/assert-2.1.0.tgz",
"integrity": "sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.2",
"is-nan": "^1.3.2",
"object-is": "^1.1.5",
"object.assign": "^4.1.4",
"util": "^0.12.5"
}
},
"node_modules/ast-kit": {
"version": "0.11.2",
"resolved": "https://registry.npmjs.org/ast-kit/-/ast-kit-0.11.2.tgz",
@ -4934,6 +4959,18 @@
"node": ">=16.14.0"
}
},
"node_modules/ast-types": {
"version": "0.16.1",
"resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz",
"integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==",
"dev": true,
"dependencies": {
"tslib": "^2.0.1"
},
"engines": {
"node": ">=4"
}
},
"node_modules/ast-walker-scope": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/ast-walker-scope/-/ast-walker-scope-0.5.0.tgz",
@ -7462,6 +7499,19 @@
"url": "https://opencollective.com/eslint"
}
},
"node_modules/esprima": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
"dev": true,
"bin": {
"esparse": "bin/esparse.js",
"esvalidate": "bin/esvalidate.js"
},
"engines": {
"node": ">=4"
}
},
"node_modules/esquery": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
@ -9053,6 +9103,22 @@
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/is-arguments": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
"integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-array-buffer": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz",
@ -9233,6 +9299,21 @@
"node": ">=8"
}
},
"node_modules/is-generator-function": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz",
"integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==",
"dev": true,
"dependencies": {
"has-tostringtag": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-glob": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
@ -9316,6 +9397,22 @@
"integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==",
"dev": true
},
"node_modules/is-nan": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz",
"integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.0",
"define-properties": "^1.1.3"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-negative-zero": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
@ -13525,6 +13622,33 @@
"url": "https://github.com/sponsors/ivodolenc"
}
},
"node_modules/nuxt-quasar-ui": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/nuxt-quasar-ui/-/nuxt-quasar-ui-2.0.6.tgz",
"integrity": "sha512-42ogT4HQgQ7IMrI9XOzrVLPMOu8b/onHr6ZX+hcLJ8Hrb+zei7hJj3rtT+l6ylG6h0aiBSmzAKJV/NqJrH89Fw==",
"dev": true,
"dependencies": {
"@nuxt/kit": "^3.7.4",
"magic-string": "^0.30.4",
"magicast": "^0.2.11",
"p-memoize": "^7.1.1"
},
"peerDependencies": {
"@quasar/extras": "^1",
"quasar": "^2.8.0"
}
},
"node_modules/nuxt-quasar-ui/node_modules/magicast": {
"version": "0.2.11",
"resolved": "https://registry.npmjs.org/magicast/-/magicast-0.2.11.tgz",
"integrity": "sha512-6saXbRDA1HMkqbsvHOU6HBjCVgZT460qheRkLhJQHWAbhXoWESI3Kn/dGGXyKs15FFKR85jsUqFx2sMK0wy/5g==",
"dev": true,
"dependencies": {
"@babel/parser": "^7.22.16",
"@babel/types": "^7.22.17",
"recast": "^0.23.4"
}
},
"node_modules/nuxt/node_modules/estree-walker": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
@ -13626,6 +13750,22 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/object-is": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz",
"integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.2",
"define-properties": "^1.1.3"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/object-keys": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
@ -13848,6 +13988,22 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/p-memoize": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/p-memoize/-/p-memoize-7.1.1.tgz",
"integrity": "sha512-DZ/bONJILHkQ721hSr/E9wMz5Am/OTJ9P6LhLFo2Tu+jL8044tgc9LwHO8g4PiaYePnlVVRAJcKmgy8J9MVFrA==",
"dev": true,
"dependencies": {
"mimic-fn": "^4.0.0",
"type-fest": "^3.0.0"
},
"engines": {
"node": ">=14.16"
},
"funding": {
"url": "https://github.com/sindresorhus/p-memoize?sponsor=1"
}
},
"node_modules/p-try": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
@ -14765,6 +14921,20 @@
"node": ">=6"
}
},
"node_modules/quasar": {
"version": "2.14.0",
"resolved": "https://registry.npmjs.org/quasar/-/quasar-2.14.0.tgz",
"integrity": "sha512-hxaQ/yd/qNGgpUrww4fQRSpklKnZN90HXhmhmPE5h+yFCcXreU+JgM3m/Mf6Qv7lMNQZQkYipgZ5Ja41DYkVUQ==",
"engines": {
"node": ">= 10.18.1",
"npm": ">= 6.13.4",
"yarn": ">= 1.21.1"
},
"funding": {
"type": "github",
"url": "https://donate.quasar.dev"
}
},
"node_modules/queue-microtask": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
@ -15055,6 +15225,31 @@
"node": ">=8.10.0"
}
},
"node_modules/recast": {
"version": "0.23.4",
"resolved": "https://registry.npmjs.org/recast/-/recast-0.23.4.tgz",
"integrity": "sha512-qtEDqIZGVcSZCHniWwZWbRy79Dc6Wp3kT/UmDA2RJKBPg7+7k51aQBZirHmUGn5uvHf2rg8DkjizrN26k61ATw==",
"dev": true,
"dependencies": {
"assert": "^2.0.0",
"ast-types": "^0.16.1",
"esprima": "~4.0.0",
"source-map": "~0.6.1",
"tslib": "^2.0.1"
},
"engines": {
"node": ">= 4"
}
},
"node_modules/recast/node_modules/source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/redis-errors": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz",
@ -17876,6 +18071,19 @@
"integrity": "sha512-Qp95D4TPJl1kC9SKigDcqgyM2VDVO4RiJc2d4qe5GrYm+zbIQCWWKAFaJNQ4BhdFeDGwBmAxqJBwWSJDb9T3BQ==",
"dev": true
},
"node_modules/util": {
"version": "0.12.5",
"resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz",
"integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==",
"dev": true,
"dependencies": {
"inherits": "^2.0.3",
"is-arguments": "^1.0.4",
"is-generator-function": "^1.0.7",
"is-typed-array": "^1.1.3",
"which-typed-array": "^1.1.2"
}
},
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",

View File

@ -27,6 +27,7 @@
"eslint-plugin-prettier": "^5.0.1",
"nuxt": "^3.8.1",
"nuxt-font-loader": "^2.3.4",
"nuxt-quasar-ui": "^2.0.6",
"prettier": "^3.0.3",
"sass": "^1.69.5",
"typescript": "^5.2.2",
@ -46,9 +47,11 @@
"@fortawesome/free-regular-svg-icons": "^6.4.2",
"@fortawesome/free-solid-svg-icons": "^6.4.2",
"@fortawesome/vue-fontawesome": "^3.0.5",
"@quasar/extras": "^1.16.8",
"animate.css": "^4.1.1",
"bootstrap": "^5.3.2",
"humps": "^2.0.1",
"pinia": "^2.1.7"
"pinia": "^2.1.7",
"quasar": "^2.14.0"
}
}

View File

@ -1,10 +1,13 @@
<script setup lang="ts">
const age =
new Date(Number(new Date()) - Number(new Date('2003-09-18'))).getFullYear() -
1970
const meta = {
title: 'About',
description:
'A software engineer, a malware enthusiast and, most importantly, a weird tall creature.',
title: 'About Me',
description: `Nice to meet you!~ I'm Andrew, a ${age}-year-old developer from Kaluga, Russia.`,
image: 'https://enderman.ch/images/logo.png',
url: 'https://enderman.ch/',
url: 'https://enderman.ch/about',
}
useSeoMeta({
@ -36,6 +39,10 @@ useHead({
})
</script>
<template><p>About page!</p></template>
<template>
<section>
<p>This page shall be added in a future release.</p>
</section>
</template>
<style scoped lang="scss"></style>

View File

@ -22,7 +22,7 @@ useSeoMeta({
})
useHead({
titleTemplate: 'Enderman',
title: 'Enderman',
htmlAttrs: {
lang: 'en',
},
@ -37,13 +37,65 @@ useHead({
</script>
<template>
<p>
A software engineer, a malware enthusiast and most importantly, a weird tall
creature.
<ClientOnly fallback-tag="span" fallback="TikTok">
<FontAwesomeIcon icon="fa-brands fa-tiktok" />
</ClientOnly>
</p>
<section>
<h3 class="alex">Welcome 👋</h3>
<p>
I'm <strong>Enderman</strong> &ndash; a software engineer, a malware
enthusiast and most importantly, a weird tall creature. I have over 300K
subscribers on
<a class="link-hi" href="https://go.enderman.ch/youtube">YouTube</a> and
over 20K followers on
<a class="link-hi" href="https://go.enderman.ch/twitter">Twitter</a>.
Sometimes I wish there were 48 hours in a day.
</p>
<div class="row g-3">
<div class="col-12 col-md-8">
<h5 class="alex">What I do</h5>
<ul>
<li>
I develop cross-platform software. My language of choice is usually
<strong>C/C++</strong> for desktop applications and any common
backend stack with framework-loaded TypeScript for web. You can take
a look at my code on
<a class="link-hi" href="https://go.enderman.ch/github">GitHub</a>.
</li>
<li>
I have the most unnecessary, yet fascinating knowledge about
Microsoft Windows, and I absolutely love sharing it with my viewers
in an unorthodox comedic fashion.
<sub>
<em>*Microsoft still has not hired me as a software tester.</em>
</sub>
</li>
<li>
I research and analyze modern malware, educate computer users about
it and preserve history. The repository can be found
<a class="link-hi" href="https://go.enderman.ch/repository">here</a
>.
</li>
<li>I make videos for you to enjoy!</li>
</ul>
</div>
<div class="col-12 col-md-4">
<h5 class="alex">What I enjoy</h5>
<ul>
<li>Teaching</li>
<li>Mathematics</li>
<li>Philosophy</li>
<li>Geopolitics</li>
<li>
<a class="link-hi" href="https://go.enderman.ch/chess">Chess</a>
</li>
<li>Solitude</li>
</ul>
</div>
</div>
<p>
<strong>Want to learn more?</strong> Find out more about me using the
navigation bar!<br />
<em>See you there!~</em>
</p>
</section>
</template>
<style scoped lang="scss"></style>

View File

@ -1,5 +1,45 @@
<script setup lang="ts"></script>
<script setup lang="ts">
const meta = {
title: "Enderman's Projects",
description:
"A display of my largest projects. Some of them aren't published on YouTube.",
image: 'https://enderman.ch/images/logo.png',
url: 'https://enderman.ch/projects',
}
<template><p>Project page!</p></template>
useSeoMeta({
title: meta.title,
description: meta.description,
ogTitle: meta.title,
ogDescription: meta.description,
ogImage: meta.image,
ogUrl: meta.url,
ogType: 'website',
twitterTitle: meta.title,
twitterDescription: meta.description,
twitterImage: meta.image,
twitterCard: 'summary',
})
useHead({
title: 'Projects',
htmlAttrs: {
lang: 'en',
},
link: [
{
rel: 'icon',
type: 'image/x-icon',
href: '/favicon.ico',
},
],
})
</script>
<template>
<section>
<p>This page shall be added in a future release.</p>
</section>
</template>
<style scoped lang="scss"></style>

View File

@ -1,12 +1,110 @@
<script setup lang="ts"></script>
<script setup lang="ts">
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
const socials = [
{
name: 'YouTube',
url: 'https://go.enderman.ch/youtube',
icon: 'youtube',
},
{
name: 'Andrew',
url: 'https://go.enderman.ch/andrew',
icon: 'youtube',
},
{
name: 'Twitch',
url: 'https://go.enderman.ch/twitch',
icon: 'twitch',
},
{
name: 'TikTok',
url: 'https://go.enderman.ch/tiktok',
icon: 'tiktok',
},
{
name: 'Twitter',
url: 'https://go.enderman.ch/twitter',
icon: 'twitter',
},
{
name: 'Telegram',
url: 'https://go.enderman.ch/telegram',
icon: 'telegram',
},
{
name: 'Discord',
url: 'https://go.enderman.ch/discord',
icon: 'discord',
},
{
name: 'GitHub',
url: 'https://go.enderman.ch/github',
icon: 'github',
},
{
name: 'Steam',
url: 'https://go.enderman.ch/steam',
icon: 'steam',
},
]
const meta = {
title: 'Enderman Online',
description:
'Discover me on your favorite social media and find ways to contact me here.',
image: 'https://enderman.ch/images/logo.png',
url: 'https://enderman.ch/projects',
}
useSeoMeta({
title: meta.title,
description: meta.description,
ogTitle: meta.title,
ogDescription: meta.description,
ogImage: meta.image,
ogUrl: meta.url,
ogType: 'website',
twitterTitle: meta.title,
twitterDescription: meta.description,
twitterImage: meta.image,
twitterCard: 'summary',
})
useHead({
title: 'Socials',
htmlAttrs: {
lang: 'en',
},
link: [
{
rel: 'icon',
type: 'image/x-icon',
href: '/favicon.ico',
},
],
})
</script>
<template>
<h3>Contact</h3>
<p>
Fanmail: contact@enderman.ch <br />
Manager: manager@enderman.ch<br />
Abuse: abuse@enderman.ch
</p>
<div>
<h3 class="alex">Social media</h3>
<ul class="list-style-type-none p-0">
<li v-for="(page, index) in socials" :key="index">
<FontAwesomeIcon :icon="`fa-brands fa-${page.icon}`" />
<a class="link-hi" target="_blank" rel="noopener" :href="page.url">{{
page.name
}}</a>
</li>
</ul>
<h3 class="alex">Contact me</h3>
<p>
Fanmail:
<EMail address="contact@enderman.ch" subject="Hey Enderman!" /><br />
Manager: <EMail address="manager@enderman.ch" /><br />
Abuse: <EMail address="abuse@enderman.ch" />
</p>
</div>
</template>
<style scoped lang="scss"></style>

0
public/robots.txt Normal file
View File

View File

@ -4,7 +4,7 @@ export const usePageStore = defineStore('page', () => {
const title: string = 'Enderman'
const description: string = 'official website'
const keywords: string =
'endermanch, enderman, developer, designer, artist, web, web developer, web designer, web artist, software, software developer, software designer, software artist, software engineer, engineer, software engineer'
'endermanch, enderman, developer, youtuber, filmmaker, artist, engineer'
const pages = ref([
{