Rewrite to TailwindCSS, enhance the DOM, uninstall Vuetify, improve styles
This commit is contained in:
+14
-21
@@ -41,27 +41,21 @@ useHead({
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section>
|
||||
<h4>About me</h4>
|
||||
<hr class="accent accent-gradient border-0 h-px" />
|
||||
<p>
|
||||
<strong>🚧 This page is currently under construction.</strong> Expect a
|
||||
lot more content to be added as time passes.
|
||||
<em>Please report all bugs you encounter via the link in the footer</em>,
|
||||
I will make sure to sand them down.
|
||||
</p>
|
||||
<hr class="accent accent-gradient border-0 h-px" />
|
||||
<section class="page">
|
||||
<h3>About me</h3>
|
||||
<Construction />
|
||||
<p>
|
||||
Nice to meet you! I'm Andrew, a {{ age }}-year-old guy from Kaluga,
|
||||
Russia. I have been developing software since I was 10, and I have always
|
||||
been interested in technology. I'm a middle-senior C/++ developer and a
|
||||
junior full-stack engineer.
|
||||
<sup>1</sup>
|
||||
</p>
|
||||
<p class="font-small">
|
||||
<sup>1</sup>
|
||||
All titles are based on knowledge and confidence, not on official work
|
||||
experience.
|
||||
<br />
|
||||
<small>
|
||||
<sup>1</sup>
|
||||
All titles are based on knowledge and confidence, not on official work
|
||||
experience.
|
||||
</small>
|
||||
</p>
|
||||
<p><strong>Here's a little more about myself:</strong></p>
|
||||
<ul>
|
||||
@@ -70,11 +64,11 @@ useHead({
|
||||
<li>My favorite field in mathematics is Algebraic Geometry.</li>
|
||||
</ul>
|
||||
<p>
|
||||
I work on all sorts of projects, most of the times simultaneously, which
|
||||
I work on all sorts of projects, most of the time simultaneously, which
|
||||
doesn't help with adhering to deadlines at all. However, you can always
|
||||
check them out!
|
||||
</p>
|
||||
<h5 class="alex">FAQ</h5>
|
||||
<h5>FAQ</h5>
|
||||
<ul class="list-style-type-faq">
|
||||
<li><strong>Why are you called Endermanch?</strong></li>
|
||||
<li>
|
||||
@@ -84,10 +78,9 @@ useHead({
|
||||
end sounded pretty good. I was 14 at the time of making that decision.
|
||||
</li>
|
||||
<li>
|
||||
<strong
|
||||
>When will you make a new video? What happened to your
|
||||
schedule?</strong
|
||||
>
|
||||
<strong>
|
||||
When will you make a new video? What happened to your schedule?
|
||||
</strong>
|
||||
</li>
|
||||
<li>
|
||||
One day. Haven't been particularly motivated lately, but life's busy. 🙁
|
||||
|
||||
+96
-71
@@ -1,15 +1,16 @@
|
||||
<script setup lang="ts">
|
||||
import { formatDate } from 'date-fns'
|
||||
import { useAsyncData } from '#app'
|
||||
import chestAnimation from '~/assets/images/chest.webp'
|
||||
|
||||
const config = useAppConfig()
|
||||
const route = useRoute()
|
||||
|
||||
let thumbnail: string | null = null
|
||||
let slug = useRoute().params.slug
|
||||
let slug = route.params.slug
|
||||
|
||||
if (Array.isArray(slug)) slug = slug.join('/')
|
||||
|
||||
const { data } = await useAsyncData('home', () =>
|
||||
const { data, status } = await useAsyncData('home', () =>
|
||||
queryContent(`/blog/${slug}`).findOne(),
|
||||
)
|
||||
|
||||
@@ -58,55 +59,55 @@ if (data.value) {
|
||||
)
|
||||
|
||||
// Hydrate the rendered items.
|
||||
onMounted(() => {
|
||||
document.querySelectorAll('pre').forEach((pre) => {
|
||||
const icon = document.createElement('iconify-icon')
|
||||
|
||||
icon.setAttribute('icon', 'mdi:content-copy')
|
||||
icon.setAttribute('inline', 'true')
|
||||
|
||||
icon.classList.add('button')
|
||||
|
||||
pre.appendChild(icon)
|
||||
})
|
||||
|
||||
document
|
||||
.querySelectorAll('code:not(pre *), pre > iconify-icon.button')
|
||||
.forEach((code) => {
|
||||
if (code instanceof HTMLElement) {
|
||||
code.onclick = () => {
|
||||
const area = document.createElement('textarea')
|
||||
|
||||
area.textContent =
|
||||
code.nodeName && code.nodeName.toLowerCase() === 'code'
|
||||
? code.textContent
|
||||
: code.parentElement!.textContent
|
||||
|
||||
// It's necessary to create the textarea element every time you copy to get access to the select() method.
|
||||
area.setSelectionRange(0, 99999) // An iOS gotcha.
|
||||
area.select()
|
||||
|
||||
// Copy the text inside the textarea.
|
||||
navigator.clipboard.writeText(area.value)
|
||||
|
||||
// TODO: Alert the user text has been successfully copied.
|
||||
|
||||
// Remove the textarea element.
|
||||
area.remove()
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
document.querySelectorAll('code').forEach((code) => {
|
||||
code.onclick = null
|
||||
})
|
||||
|
||||
document.querySelectorAll('pre').forEach((pre) => {
|
||||
pre.querySelector('.clipboard')?.remove()
|
||||
})
|
||||
})
|
||||
// onMounted(() => {
|
||||
// document.querySelectorAll('pre').forEach((pre) => {
|
||||
// const icon = document.createElement('iconify-icon')
|
||||
//
|
||||
// icon.setAttribute('icon', 'mdi:content-copy')
|
||||
// icon.setAttribute('inline', 'true')
|
||||
//
|
||||
// icon.classList.add('button')
|
||||
//
|
||||
// pre.appendChild(icon)
|
||||
// })
|
||||
//
|
||||
// document
|
||||
// .querySelectorAll('code:not(pre *), pre > iconify-icon.button')
|
||||
// .forEach((code) => {
|
||||
// if (code instanceof HTMLElement) {
|
||||
// code.onclick = () => {
|
||||
// const area = document.createElement('textarea')
|
||||
//
|
||||
// area.textContent =
|
||||
// code.nodeName && code.nodeName.toLowerCase() === 'code'
|
||||
// ? code.textContent
|
||||
// : code.parentElement!.textContent
|
||||
//
|
||||
// // It's necessary to create the textarea element every time you copy to get access to the select() method.
|
||||
// area.setSelectionRange(0, 99999) // An iOS gotcha.
|
||||
// area.select()
|
||||
//
|
||||
// // Copy the text inside the textarea.
|
||||
// navigator.clipboard.writeText(area.value)
|
||||
//
|
||||
// // TODO: Alert the user text has been successfully copied.
|
||||
//
|
||||
// // Remove the textarea element.
|
||||
// area.remove()
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
// })
|
||||
//
|
||||
// onUnmounted(() => {
|
||||
// document.querySelectorAll('code').forEach((code) => {
|
||||
// code.onclick = null
|
||||
// })
|
||||
//
|
||||
// document.querySelectorAll('pre').forEach((pre) => {
|
||||
// pre.querySelector('.clipboard')?.remove()
|
||||
// })
|
||||
// })
|
||||
}
|
||||
|
||||
useHead({
|
||||
@@ -125,44 +126,68 @@ useHead({
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
v-if="status === 'pending'"
|
||||
class="flex flex-col items-center justify-center gap-4 w-full select-none text-center"
|
||||
>
|
||||
<img draggable="false" :src="chestAnimation" alt="The Ender Chest" />
|
||||
<div>
|
||||
<h1 class="font-enchant">Loading document...</h1>
|
||||
<span class="opacity-0 hover:opacity-100 transition-ease">
|
||||
<em>Loading document...</em>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<article
|
||||
v-if="data"
|
||||
class="post scrollbar fade-mask-sm flex flex-col gap-3 flex-grow-1 overflow-x-hidden overflow-y-auto sm:py-4 sm:pe-3"
|
||||
v-else-if="status === 'success' && data"
|
||||
class="flex-grow post fade-mask-sm flex flex-col gap-4 overflow-x-hidden overflow-y-auto sm:py-4 sm:pe-4"
|
||||
>
|
||||
<div
|
||||
class="post-preamble"
|
||||
class="relative flex flex-col justify-end items-start w-full min-h-[400px] rounded-xl accent-text-shadow post-preamble"
|
||||
:style="{ backgroundImage: 'url(' + thumbnail + ')' }"
|
||||
>
|
||||
<div class="p-2">
|
||||
<h3 class="alex">{{ data.title }}</h3>
|
||||
<div class="flex flex-row gap-x-0 gap-y-2 flex-wrap">
|
||||
<div class="flex flex-row items-center gap-1">
|
||||
<h3>{{ data.title }}</h3>
|
||||
<div class="flex flex-row flex-wrap gap-x-2 gap-y-0">
|
||||
<div class="flex flex-row items-center gap-2">
|
||||
<iconify-icon icon="mdi:calendar" />
|
||||
<strong class="nobr font-small">
|
||||
{{ formatDate(data.created, 'LLLL do, y – HH:mm') }}
|
||||
</strong>
|
||||
<small class="whitespace-nowrap">
|
||||
<strong>
|
||||
{{ formatDate(data.created, 'LLLL do, y – HH:mm') }}
|
||||
</strong>
|
||||
</small>
|
||||
</div>
|
||||
<div class="flex flex-row items-center gap-1">
|
||||
<div class="flex flex-row items-center gap-2">
|
||||
<iconify-icon icon="mdi:clock-outline" />
|
||||
<strong class="nobr font-small">
|
||||
{{ data!.readingTime.text.split(' ')[0] + ' minutes to read' }}
|
||||
</strong>
|
||||
<small class="whitespace-nowrap">
|
||||
<strong>
|
||||
{{ data!.readingTime.text.split(' ')[0] + ' minutes to read' }}
|
||||
</strong>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<NuxtLink
|
||||
to="/blog"
|
||||
class="absolute top-0 left-0 p-2 text-inherit no-underline"
|
||||
>
|
||||
<iconify-icon
|
||||
icon="icon-park-solid:back"
|
||||
width="2em"
|
||||
height="2em"
|
||||
style="color: lavender"
|
||||
/>
|
||||
</NuxtLink>
|
||||
<NuxtLink
|
||||
:href="`https://twitter.com/share?url=${config.url}/blog/${slug}&text=${data.title}&hashtags=${data.tags.slice(0, 3).join(',').replace(/ /g, '')}`"
|
||||
target="_blank"
|
||||
class="link post-preamble-share px-2 py-1"
|
||||
class="absolute top-0 right-0 p-2"
|
||||
>
|
||||
<iconify-icon icon="mdi:twitter"></iconify-icon>
|
||||
</NuxtLink>
|
||||
<NuxtLink to="/blog" class="link post-preamble-control px-2 py-1">
|
||||
<iconify-icon icon="icon-park-solid:back"></iconify-icon>
|
||||
<iconify-icon icon="logos:twitter" width="2em" height="2em" />
|
||||
</NuxtLink>
|
||||
</div>
|
||||
<div class="post-content">
|
||||
<hr class="accent accent-gradient border-0 h-px" />
|
||||
<hr class="accent-text accent-gradient border-0 h-px" />
|
||||
<ContentRenderer :value="data" />
|
||||
</div>
|
||||
</article>
|
||||
|
||||
+23
-23
@@ -3,7 +3,7 @@ import { formatDate } from 'date-fns'
|
||||
|
||||
const config = useAppConfig()
|
||||
const meta = {
|
||||
title: 'The Enderchest',
|
||||
title: 'The Ender Chest',
|
||||
description:
|
||||
'A blog about software development, scientific research and Windows quirks.',
|
||||
image: `${config.url}/images/chest.png`,
|
||||
@@ -25,7 +25,7 @@ useSeoMeta({
|
||||
})
|
||||
|
||||
useHead({
|
||||
title: 'The Enderchest',
|
||||
title: 'The Ender Chest',
|
||||
htmlAttrs: {
|
||||
lang: config.locale || 'en',
|
||||
},
|
||||
@@ -41,12 +41,12 @@ useHead({
|
||||
|
||||
<template>
|
||||
<section>
|
||||
<h3 class="alex">The Enderchest</h3>
|
||||
<p>
|
||||
You're browsing the enderchest — a blog about software development,
|
||||
<h3 class="mb-2">The Ender Chest</h3>
|
||||
<p class="mb-4">
|
||||
You're browsing the Ender Chest — a blog about software development,
|
||||
scientific research and Windows quirks.
|
||||
</p>
|
||||
<h4 class="alex">Recent posts</h4>
|
||||
<h4 class="mb-2">Recent posts</h4>
|
||||
<ContentList
|
||||
:query="{
|
||||
path: '/blog',
|
||||
@@ -56,15 +56,15 @@ useHead({
|
||||
}"
|
||||
>
|
||||
<template #default="{ list }">
|
||||
<div class="grid gap-3">
|
||||
<div class="grid gap-4">
|
||||
<NuxtLink
|
||||
v-for="post in list"
|
||||
:key="post._path"
|
||||
:to="post._path"
|
||||
class="no-decoration"
|
||||
class="text-inherit hover:text-inherit no-underline"
|
||||
>
|
||||
<article
|
||||
class="post-box flex flex-col md:flex-row gap-3 rounded-xl h-full"
|
||||
class="post-box flex flex-col md:flex-row gap-4 rounded-xl h-full"
|
||||
>
|
||||
<div class="post-thumb">
|
||||
<img
|
||||
@@ -78,46 +78,48 @@ useHead({
|
||||
/>
|
||||
</div>
|
||||
<div class="w-full">
|
||||
<h3 class="post-title alex">{{ post.title }}</h3>
|
||||
<h3 class="post-title">{{ post.title }}</h3>
|
||||
<p class="post-description mb-0">{{ post.description }}</p>
|
||||
|
||||
<div class="post-tags flex flex-row flex-wrap gap-2 py-2">
|
||||
<span
|
||||
v-for="(tag, index) in post.tags.slice(0, 3)"
|
||||
:key="index"
|
||||
class="nobr"
|
||||
class="whitespace-nowrap"
|
||||
>
|
||||
{{ tag }}
|
||||
</span>
|
||||
<span v-if="post.tags.length > 3" class="nobr">
|
||||
<span v-if="post.tags.length > 3" class="whitespace-nowrap">
|
||||
{{ post.tags.length - 3 }} more
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<hr class="accent accent-gradient border-0 h-px" />
|
||||
<hr class="accent-text accent-gradient border-0 h-px" />
|
||||
|
||||
<div class="post-details py-2">
|
||||
<div class="flex flex-row items-center gap-1">
|
||||
<div class="flex flex-row items-center gap-2">
|
||||
<iconify-icon icon="mdi:calendar" />
|
||||
<small class="nobr">
|
||||
<small class="whitespace-nowrap">
|
||||
{{ formatDate(post.created, 'LLLL do, y – HH:mm') }}
|
||||
</small>
|
||||
</div>
|
||||
<div
|
||||
v-if="post.updated"
|
||||
class="flex flex-row items-center gap-1"
|
||||
class="flex flex-row items-center gap-2"
|
||||
>
|
||||
<iconify-icon icon="mdi:pencil" />
|
||||
<small class="nobr">
|
||||
<small class="whitespace-nowrap">
|
||||
{{ formatDate(post.updated, 'LLLL do, y – HH:mm') }}
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="post-pocket flex flex-row items-center gap-1 p-2">
|
||||
<div
|
||||
class="post-pocket absolute bottom-0 right-0 uppercase rounded-tl-xl flex flex-row items-center gap-2 p-2"
|
||||
>
|
||||
<iconify-icon icon="mdi:clock-outline" />
|
||||
<small class="nobr font-monospace font-small">
|
||||
<small class="whitespace-nowrap font-mono font-small">
|
||||
{{ post.readingTime.text }}
|
||||
</small>
|
||||
</div>
|
||||
@@ -127,13 +129,11 @@ useHead({
|
||||
</template>
|
||||
|
||||
<template #not-found>
|
||||
<div class="flex flex-col justify-center items-center gap-3">
|
||||
<div class="flex flex-col justify-center items-center gap-4">
|
||||
<span>No posts found 🙁</span>
|
||||
<NuxtLink to="/" class="link-hi">Back to index</NuxtLink>
|
||||
<NuxtLink to="/">Back to index</NuxtLink>
|
||||
</div>
|
||||
</template>
|
||||
</ContentList>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
|
||||
+8
-10
@@ -46,18 +46,17 @@ defineRouteRules({
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section>
|
||||
<section class="page">
|
||||
<h3>Welcome 👋</h3>
|
||||
<p class="mb-4">
|
||||
<p>
|
||||
I'm <strong>Enderman</strong> – a software engineer, a malware
|
||||
enthusiast and most importantly, a weird tall creature. I have over 300K
|
||||
subscribers on <a :href="`${config.shortener}/youtube`">YouTube</a> and
|
||||
over 25K followers on
|
||||
<a class="text-inherit no-underline" :href="`${config.shortener}/twitter`"
|
||||
>Twitter</a
|
||||
>. Sometimes I wish there were 48 hours in a day.
|
||||
<a :href="`${config.shortener}/twitter`">Twitter</a>. Sometimes I wish
|
||||
there were 48 hours in a day.
|
||||
</p>
|
||||
<div class="flex flex-col md:flex-row gap-3 mb-4">
|
||||
<div class="flex flex-col md:flex-row gap-4">
|
||||
<div class="md:basis-0 md:flex-grow-[2]">
|
||||
<h6>What I do</h6>
|
||||
<ul class="list-style-type-do">
|
||||
@@ -66,7 +65,7 @@ defineRouteRules({
|
||||
<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="`${config.shortener}/github`">GitHub</a>.
|
||||
<a :href="`${config.shortener}/github`">GitHub</a>.
|
||||
</li>
|
||||
<li>
|
||||
I have the most unnecessary, yet fascinating knowledge about
|
||||
@@ -79,8 +78,7 @@ defineRouteRules({
|
||||
<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="`${config.shortener}/repository`">here</a
|
||||
>.
|
||||
<a :href="`${config.shortener}/repository`">here</a>.
|
||||
</li>
|
||||
<li>I make videos for you to enjoy!</li>
|
||||
</ul>
|
||||
@@ -95,7 +93,7 @@ defineRouteRules({
|
||||
<li>Philosophy</li>
|
||||
<li>Geopolitics</li>
|
||||
<li>
|
||||
<a class="link-hi" :href="`${config.shortener}/chess`">Chess</a>
|
||||
<a :href="`${config.shortener}/chess`">Chess</a>
|
||||
</li>
|
||||
<li>Solitude</li>
|
||||
</ul>
|
||||
|
||||
+4
-11
@@ -67,20 +67,13 @@ useHead({
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section>
|
||||
<h3 class="alex">Projects</h3>
|
||||
<hr class="accent accent-gradient border-0 h-px" />
|
||||
<p>
|
||||
<strong>🚧 This page is currently under construction.</strong> Expect a
|
||||
lot more content to be added as time passes.
|
||||
<em>Please report all bugs you encounter via the link in the footer</em>,
|
||||
I will make sure to sand them down.
|
||||
</p>
|
||||
<hr class="accent accent-gradient border-0 h-px" />
|
||||
<section class="page">
|
||||
<h3>Projects</h3>
|
||||
<Construction />
|
||||
<p><strong>My current projects are:</strong></p>
|
||||
<ul>
|
||||
<li v-for="(item, index) in projects" :key="index">
|
||||
<a class="link-hi" :href="item.url">
|
||||
<a :href="item.url">
|
||||
{{ item.name }}
|
||||
</a>
|
||||
</li>
|
||||
|
||||
+20
-25
@@ -115,39 +115,34 @@ useHead({
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section>
|
||||
<h3 class="alex">Online presence</h3>
|
||||
<hr class="accent accent-gradient border-0 h-px" />
|
||||
<p>
|
||||
<strong>🚧 This page is currently under construction.</strong> Expect a
|
||||
lot more content to be added as time passes.
|
||||
<em>Please report all bugs you encounter via the link in the footer</em>,
|
||||
I will make sure to sand them down.
|
||||
</p>
|
||||
<hr class="accent accent-gradient border-0 h-px" />
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-3">
|
||||
<h5 class="alex">Social media</h5>
|
||||
<section class="page">
|
||||
<h3>Online presence</h3>
|
||||
<Construction />
|
||||
<div class="flex flex-col md:flex-row gap-4">
|
||||
<div class="md:basis-0 md:flex-grow-[1]">
|
||||
<h5>Social media</h5>
|
||||
<ul class="list-style-type-none p-0">
|
||||
<li v-for="(page, index) in socials" :key="index">
|
||||
<a class="link-hi" target="_blank" rel="noopener" :href="page.url">
|
||||
<Icon :name="page.icon.name" :color="page.icon.color" inline />
|
||||
<NuxtLink target="_blank" rel="noopener" :href="page.url">
|
||||
<iconify-icon
|
||||
:icon="page.icon.name"
|
||||
:style="{ color: page.icon.color }"
|
||||
width="1em"
|
||||
height="1em"
|
||||
inline
|
||||
/>
|
||||
<span class="mx-2">{{ page.name }}</span>
|
||||
</a>
|
||||
</NuxtLink>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-12 col-md-9">
|
||||
<h5 class="alex">Contact me</h5>
|
||||
<div class="md:basis-0 md:flex-grow-[3]">
|
||||
<h5>Contact me</h5>
|
||||
<p>
|
||||
Personal:
|
||||
<EMail
|
||||
class="link-hi"
|
||||
:address="`contact@${fqdn}`"
|
||||
subject="Hey Enderman!"
|
||||
/><br />
|
||||
Manager: <EMail class="link-hi" :address="`manager@${fqdn}`" /><br />
|
||||
Abuse: <EMail class="link-hi" :address="`abuse@${fqdn}`" />
|
||||
<EMail :address="`contact@${fqdn}`" subject="Hey Enderman!" /><br />
|
||||
Manager: <EMail :address="`manager@${fqdn}`" /><br />
|
||||
Abuse: <EMail :address="`abuse@${fqdn}`" />
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user