switch to Astro
@@ -0,0 +1,37 @@
|
||||
name: Deploy to GitHub Pages
|
||||
|
||||
on:
|
||||
# Trigger the workflow every time you push to the `main` branch
|
||||
# Using a different branch name? Replace `main` with your branch’s name
|
||||
push:
|
||||
branches: [ main ]
|
||||
# Allows you to run this workflow manually from the Actions tab on GitHub.
|
||||
workflow_dispatch:
|
||||
|
||||
# Allow this job to clone the repo and create a page deployment
|
||||
permissions:
|
||||
contents: read
|
||||
pages: write
|
||||
id-token: write
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout your repository using git
|
||||
uses: actions/checkout@v4
|
||||
- name: Install, build, and upload your site
|
||||
uses: withastro/action@v2
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
deploy:
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
steps:
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v4
|
||||
@@ -0,0 +1,20 @@
|
||||
# build output
|
||||
dist/
|
||||
.output/
|
||||
|
||||
# dependencies
|
||||
node_modules/
|
||||
|
||||
# logs
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
|
||||
# environment variables
|
||||
.env
|
||||
.env.production
|
||||
|
||||
# macOS-specific files
|
||||
.DS_Store
|
||||
@@ -0,0 +1,2 @@
|
||||
# Expose Astro dependencies for `pnpm` users
|
||||
shamefully-hoist=true
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"startCommand": "npm start",
|
||||
"env": {
|
||||
"ENABLE_CJS_IMPORTS": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import { defineConfig } from 'astro/config'
|
||||
import svelte from '@astrojs/svelte'
|
||||
import mdx from '@astrojs/mdx'
|
||||
import remarkGfm from 'remark-gfm'
|
||||
import remarkSmartypants from 'remark-smartypants'
|
||||
import rehypeExternalLinks from 'rehype-external-links'
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
site: 'https://youhavetrouble.me',
|
||||
integrations: [mdx(), svelte()],
|
||||
markdown: {
|
||||
shikiConfig: {
|
||||
theme: 'nord',
|
||||
},
|
||||
remarkPlugins: [remarkGfm, remarkSmartypants],
|
||||
rehypePlugins: [
|
||||
[
|
||||
rehypeExternalLinks,
|
||||
{
|
||||
target: '_blank',
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
})
|
||||
|
Before Width: | Height: | Size: 111 KiB |
|
Before Width: | Height: | Size: 146 KiB |
|
Before Width: | Height: | Size: 154 KiB |
|
Before Width: | Height: | Size: 193 KiB |
|
Before Width: | Height: | Size: 98 KiB |
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 8.1 KiB |
|
Before Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 87 KiB |
|
Before Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 18 KiB |
@@ -1,22 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<defs>
|
||||
<linearGradient id="g" x1="0" y1="0" x2="100" y2="100" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="15%" stop-color="#25b8ff" />
|
||||
<stop offset="85%" stop-color="#fa02ff" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g fill="none" stroke="url(#g)" stroke-linejoin="round" stroke-width="1.8">
|
||||
<path d="M72.09 13.86L53.18 24.8l18.93 10.92 18.91-10.94z"/>
|
||||
<path d="M49.87 1.05L30.95 11.99 49.88 22.9 68.8 11.97z"/>
|
||||
<path d="M27.67 13.89L8.75 24.82l18.93 10.92 18.91-10.93z"/>
|
||||
<path d="M49.89 26.7L30.97 37.64 49.9 48.55l18.92-10.93z"/>
|
||||
<path d="M7.11 27.67l.01 21.86 18.93 10.91-.01-21.85z"/>
|
||||
<path d="M29.33 40.49l.01 21.85 18.93 10.92-.01-21.85z"/>
|
||||
<path d="M7.12 53.32l.01 21.85 18.93 10.91-.01-21.85z"/>
|
||||
<path d="M29.34 66.14l.01 21.85L48.28 98.9l-.01-21.85z"/>
|
||||
<path d="M51.57 98.9l18.92-10.93-.01-21.85-18.92 10.93z"/>
|
||||
<path d="M73.78 86.06L92.7 75.13l-.02-21.85-18.91 10.93z"/>
|
||||
<path d="M73.76 60.41l18.92-10.93-.01-21.85-18.92 10.93z"/>
|
||||
<path d="M51.55 51.4l.01 21.85 18.91-10.93-.01-21.85z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.1 KiB |
@@ -1,329 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>YouHaveTrouble</title>
|
||||
<meta name="title" content="YouHaveTrouble"/>
|
||||
<meta name="description" content="Just a page about random person on the internet"/>
|
||||
<meta property="twitter:title" content="YouHaveTrouble"/>
|
||||
<meta property="twitter:image" content="https://youhavetrouble.me/img/avatar.png"/>
|
||||
<meta property="twitter:description" content="Just a page about random person on the internet"/>
|
||||
<meta property="og:title" content="YouHaveTrouble"/>
|
||||
<meta property="og:url" content="https://youhavetrouble.me"/>
|
||||
<meta property="og:description" content="Just a page about random person on the internet"/>
|
||||
<meta property="og:image" content="https://youhavetrouble.me/img/avatar.png"/>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="reset.css">
|
||||
<link rel="stylesheet" href="main.css">
|
||||
<link rel="icon" href="/favicon.ico"/>
|
||||
<script src="index.js" defer></script>
|
||||
</head>
|
||||
<body>
|
||||
<nav>
|
||||
<a data-link="about" tabindex="1" href="#about">About me</a>
|
||||
<a data-link="socials" tabindex="2" href="#socials">Socials</a>
|
||||
<a data-link="projects" tabindex="3" href="#projects">Projects</a>
|
||||
</nav>
|
||||
<main>
|
||||
<section id="about">
|
||||
<div class="bg"></div>
|
||||
<article>
|
||||
<div>
|
||||
<h1>YouHaveTrouble</h1>
|
||||
<small style="display: block" class="text-center">Just a random person on the internet</small>
|
||||
</div>
|
||||
<div data-info class="tags">
|
||||
<span>Creative</span>
|
||||
<span>Frontend</span>
|
||||
<span>Backend</span>
|
||||
<span>Developer</span>
|
||||
<span>Web</span>
|
||||
<span>Modder</span>
|
||||
<span>Gamer</span>
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
<hr>
|
||||
<section id="socials">
|
||||
<div class="bg"></div>
|
||||
<h2>Socials</h2>
|
||||
<article>
|
||||
<a href="https://github.com/YouHaveTrouble" class="social-link" target="_blank" rel="external">
|
||||
<img src="img/icon/github.svg" alt="GitHub" draggable="false" loading="lazy">
|
||||
<span>GitHub</span>
|
||||
</a>
|
||||
<a href="https://discord.youhavetrouble.me" class="social-link" target="_blank" rel="external">
|
||||
<img src="img/icon/discord.svg" alt="Discord" draggable="false" loading="lazy">
|
||||
<span>Discord</span>
|
||||
</a>
|
||||
<a href="https://ko-fi.com/youhavetrouble" class="social-link" target="_blank" rel="external">
|
||||
<img src="img/icon/kofi.svg" alt="Ko-fi" draggable="false" loading="lazy">
|
||||
<span>Ko-fi</span>
|
||||
</a>
|
||||
<a href="https://steamcommunity.com/id/YouHavetrouble" class="social-link" target="_blank" rel="external">
|
||||
<img src="img/icon/steam.svg" alt="Steam" draggable="false" loading="lazy">
|
||||
<span>Steam</span>
|
||||
</a>
|
||||
<a href="https://www.youtube.com/@YouHaveTrouble" class="social-link" target="_blank" rel="external">
|
||||
<img src="img/icon/youtube.svg" alt="YouTube" draggable="false" loading="lazy">
|
||||
<span>YouTube</span>
|
||||
</a>
|
||||
<a href="https://modrinth.com/user/YouHaveTrouble" class="social-link" target="_blank" rel="external">
|
||||
<img src="img/icon/modrinth.svg" alt="Modrinth" draggable="false" loading="lazy">
|
||||
<span>Modrinth</span>
|
||||
</a>
|
||||
<a href="https://wakatime.com/@YouHaveTrouble" class="social-link" target="_blank" rel="external">
|
||||
<img src="img/icon/wakatime.svg" alt="WakaTime" draggable="false" loading="lazy">
|
||||
<span>WakaTime</span>
|
||||
</a>
|
||||
<a href="https://open.spotify.com/user/11144490753" class="social-link" target="_blank" rel="external">
|
||||
<img src="img/icon/spotify.svg" alt="Spotify" draggable="false" loading="lazy">
|
||||
<span>Spotify</span>
|
||||
</a>
|
||||
<a href="https://www.linkedin.com/in/pawel-youhavetrouble-michalewski/" class="social-link" target="_blank" rel="external">
|
||||
<img src="img/icon/linkedin.svg" alt="LinkedIn" draggable="false" loading="lazy">
|
||||
<span>LinkedIn</span>
|
||||
</a>
|
||||
<a href="mailto://contact@youhavetrouble.me" class="social-link" target="_blank" rel="external">
|
||||
<img src="img/icon/email.svg" alt="Email" draggable="false" loading="lazy">
|
||||
<span>Email</span>
|
||||
</a>
|
||||
</article>
|
||||
</section>
|
||||
<hr>
|
||||
<section id="projects">
|
||||
<div class="bg"></div>
|
||||
<h2>Projects</h2>
|
||||
<div class="project-scroller">
|
||||
<article>
|
||||
<div class="project-logo">
|
||||
<img src="/img/purpur.svg" alt="Purpur logo" draggable="false" loading="lazy">
|
||||
</div>
|
||||
<div class="description">
|
||||
<h3 class="title">Purpur</h3>
|
||||
<p>
|
||||
Minecraft server software based on Paper. Focuses on introducing new configuration options to
|
||||
already existing features along with adding completely new features.
|
||||
</p>
|
||||
<div class="links">
|
||||
<a href="https://purpurmc.org" target="_blank" rel="external" title="Project's website">
|
||||
<button>
|
||||
<img src="img/icon/website.svg" alt="website" draggable="false">
|
||||
</button>
|
||||
</a>
|
||||
<a href="https://github.com/PurpurMC/Purpur" target="_blank" rel="external" title="Project's GitHub">
|
||||
<button>
|
||||
<img src="img/icon/github.svg" alt="github" draggable="false">
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
<article>
|
||||
<div class="project-logo">
|
||||
<img src="/img/purpur.svg" alt="Purpur logo" draggable="false" loading="lazy">
|
||||
</div>
|
||||
<div class="description">
|
||||
<h3 class="title">PurpurExtras</h3>
|
||||
<p>
|
||||
Minecraft plugin for Paper and Purpur servers. Adds features that were suggested to be added in
|
||||
Purpur, but were deemed to be easier to maintain in a plugin.
|
||||
</p>
|
||||
<div class="links">
|
||||
<a href="https://modrinth.com/plugin/purpurextras" target="_blank" rel="external" title="Project's website">
|
||||
<button>
|
||||
<img src="img/icon/website.svg" alt="website" draggable="false">
|
||||
</button>
|
||||
</a>
|
||||
<a href="https://github.com/PurpurMC/PurpurExtras" target="_blank" rel="external" title="Project's GitHub">
|
||||
<button>
|
||||
<img src="img/icon/github.svg" alt="github" draggable="false">
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
<article>
|
||||
<div class="project-logo">
|
||||
<img src="/img/cw.jpeg" alt="CommandWhitelist logo" draggable="false" loading="lazy">
|
||||
</div>
|
||||
<div class="description">
|
||||
<h3 class="title">CommandWhitelist</h3>
|
||||
<p>
|
||||
Minecraft plugin for bukkit-based servers and major minecraft proxies. Allows server owners to
|
||||
decide which commands can be tab-completed and executed by players.
|
||||
</p>
|
||||
<div class="links">
|
||||
<a href="https://modrinth.com/plugin/commandwhitelist" target="_blank" rel="external" title="Project's website">
|
||||
<button>
|
||||
<img src="img/icon/website.svg" alt="website" draggable="false">
|
||||
</button>
|
||||
</a>
|
||||
<a href="https://github.com/YouHaveTrouble/CommandWhitelist" target="_blank" rel="external" title="Project's GitHub">
|
||||
<button>
|
||||
<img src="img/icon/github.svg" alt="github" draggable="false">
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
<article>
|
||||
<div class="project-logo">
|
||||
<img src="/img/ps.jpeg" alt="PreventStabby logo" draggable="false" loading="lazy">
|
||||
</div>
|
||||
<div class="description">
|
||||
<h3 class="title">PreventStabby</h3>
|
||||
<p>
|
||||
Minecraft plugin for bukkit-based servers that controls players personal PvP state, tracks all
|
||||
sources of damage for its checks and has basic combat timer tracker.
|
||||
</p>
|
||||
<div class="links">
|
||||
<a href="https://modrinth.com/plugin/preventstabby" target="_blank" rel="external" title="Project's website">
|
||||
<button>
|
||||
<img src="img/icon/website.svg" alt="website" draggable="false">
|
||||
</button>
|
||||
</a>
|
||||
<a href="https://github.com/YouHaveTrouble/PreventStabby" target="_blank" rel="external" title="Project's GitHub">
|
||||
<button>
|
||||
<img src="img/icon/github.svg" alt="github" draggable="false">
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
<article>
|
||||
<div class="project-logo">
|
||||
<img src="/img/ce.jpg" alt="Censura logo" draggable="false" loading="lazy">
|
||||
</div>
|
||||
<div class="description">
|
||||
<h3 class="title">Censura</h3>
|
||||
<p>
|
||||
Minecraft plugin for bukkit-based servers that cancels messages, item renames, writing in books
|
||||
or signs if they contain blacklisted words or regex expressions.
|
||||
</p>
|
||||
<div class="links">
|
||||
<a href="https://modrinth.com/plugin/censura" target="_blank" rel="external" title="Project's website">
|
||||
<button>
|
||||
<img src="img/icon/website.svg" alt="website" draggable="false">
|
||||
</button>
|
||||
</a>
|
||||
<a href="https://github.com/YouHaveTrouble/Censura" target="_blank" rel="external" title="Project's GitHub">
|
||||
<button>
|
||||
<img src="img/icon/github.svg" alt="github" draggable="false">
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
<article>
|
||||
<div class="project-logo">
|
||||
<img src="/img/gm.png" alt="Guild Master logo" draggable="false" loading="lazy">
|
||||
</div>
|
||||
<div class="description">
|
||||
<h3 class="title">Guild Master</h3>
|
||||
<p>
|
||||
Guild Master is a web browser game about managing a guild of adventurers. It is currently in
|
||||
early development, but is already playable.
|
||||
</p>
|
||||
<div class="links">
|
||||
<a href="https://guildmaster.yht.one" target="_blank" rel="external" title="Project's website">
|
||||
<button>
|
||||
<img src="img/icon/website.svg" alt="website" draggable="false">
|
||||
</button>
|
||||
</a>
|
||||
<a href="https://github.com/YouHaveTrouble/GuildMaster" target="_blank" rel="external" title="Project's GitHub">
|
||||
<button>
|
||||
<img src="img/icon/github.svg" alt="github" draggable="false">
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
<article>
|
||||
<div class="project-logo">
|
||||
<img src="/img/meapi.png" alt="Me API logo" draggable="false" loading="lazy">
|
||||
</div>
|
||||
<div class="description">
|
||||
<h3 class="title">Me API</h3>
|
||||
<p>
|
||||
API that allows you to query your current activity, status and game profiles.
|
||||
</p>
|
||||
<div class="links">
|
||||
<a href="https://api.youhavetrouble.me" target="_blank" rel="external" title="Project's website">
|
||||
<button>
|
||||
<img src="img/icon/website.svg" alt="website" draggable="false">
|
||||
</button>
|
||||
</a>
|
||||
<a href="https://github.com/YouHaveTrouble/MeAPI" target="_blank" rel="external" title="Project's GitHub">
|
||||
<button>
|
||||
<img src="img/icon/github.svg" alt="github" draggable="false">
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
<article>
|
||||
<div class="project-logo">
|
||||
<img src="/img/interesting-website-of-the-day.png" alt="Interesting website of the day logo" draggable="false" loading="lazy">
|
||||
</div>
|
||||
<div class="description">
|
||||
<h3 class="title">Interesting website of the day</h3>
|
||||
<p>
|
||||
Daily showcase of interesting websites from my personal database.
|
||||
</p>
|
||||
<div class="links">
|
||||
<a href="https://interesting-website.yht.one" target="_blank" rel="external" title="Project's website">
|
||||
<button>
|
||||
<img src="img/icon/website.svg" alt="website" draggable="false">
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
<article>
|
||||
<div class="project-logo">
|
||||
<img src="/img/dumb-forks-generator.png" alt="Dumb forks generator logo" draggable="false" loading="lazy">
|
||||
</div>
|
||||
<div class="description">
|
||||
<h3 class="title">Dumb forks name generator</h3>
|
||||
<p>
|
||||
Small PHP name generator for dumb minecraft server software fork names.
|
||||
</p>
|
||||
<div class="links">
|
||||
<a href="https://dumbforks.yht.one" target="_blank" rel="external" title="Project's website">
|
||||
<button>
|
||||
<img src="img/icon/website.svg" alt="website" draggable="false">
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
<article>
|
||||
<div class="project-logo">
|
||||
<img src="/img/guess-the-anime.png" alt="Guess the anime logo" draggable="false" loading="lazy">
|
||||
</div>
|
||||
<div class="description">
|
||||
<h3 class="title">Guess the Anime</h3>
|
||||
<p>
|
||||
A web game where you guess an anime title based off blurred art and a synopsis.
|
||||
</p>
|
||||
<div class="links">
|
||||
<a href="https://guessanime.yht.one" target="_blank" rel="external" title="Project's website">
|
||||
<button>
|
||||
<img src="img/icon/website.svg" alt="website" draggable="false">
|
||||
</button>
|
||||
</a>
|
||||
<a href="https://github.com/YouHaveTrouble/GuessTheAnime" target="_blank" rel="external" title="Project's GitHub">
|
||||
<button>
|
||||
<img src="img/icon/github.svg" alt="github" draggable="false">
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,68 +0,0 @@
|
||||
const sections = document.querySelectorAll('main section');
|
||||
const navLinks = document.querySelectorAll('[data-link]');
|
||||
|
||||
const observer = new IntersectionObserver((entries) => {
|
||||
if (window.innerWidth <= 767) return;
|
||||
entries.forEach(entry => {
|
||||
if (entry.isIntersecting) {
|
||||
const sectionId = entry.target.id;
|
||||
setActiveLink(sectionId);
|
||||
}
|
||||
});
|
||||
}, {
|
||||
root: null,
|
||||
rootMargin: '-10% 0px -10% 0px',
|
||||
threshold: 0.3
|
||||
});
|
||||
|
||||
const mobileObserver = new IntersectionObserver((entries) => {
|
||||
if (window.innerWidth > 767) return;
|
||||
entries.forEach(entry => {
|
||||
if (entry.isIntersecting) {
|
||||
const sectionId = entry.target.id;
|
||||
setActiveLink(sectionId);
|
||||
}
|
||||
});
|
||||
}, {
|
||||
root: null,
|
||||
rootMargin: '-20% 0px -20% 0px',
|
||||
threshold: 0.1
|
||||
});
|
||||
|
||||
sections.forEach(section => {
|
||||
observer.observe(section);
|
||||
mobileObserver.observe(section);
|
||||
});
|
||||
|
||||
function setActiveLink(sectionId) {
|
||||
navLinks.forEach(link => {
|
||||
link.classList.remove('active');
|
||||
if (link.getAttribute('data-link') === sectionId) {
|
||||
link.classList.add('active');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/** Shuffle data-info elements */
|
||||
function shuffleArray(array) {
|
||||
for (let i = array.length - 1; i > 0; i--) {
|
||||
const j = Math.floor(Math.random() * (i + 1));
|
||||
[array[i], array[j]] = [array[j], array[i]];
|
||||
}
|
||||
}
|
||||
|
||||
const dataInfo = document.querySelector("[data-info]");
|
||||
const dataInfoElements = [];
|
||||
for (const element of dataInfo.children) {
|
||||
dataInfoElements.push(element);
|
||||
}
|
||||
shuffleArray(dataInfoElements);
|
||||
dataInfo.innerHTML = "";
|
||||
for (const element of dataInfoElements) {
|
||||
dataInfo.appendChild(element);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,359 +0,0 @@
|
||||
:root {
|
||||
--text-color: #cccccc;
|
||||
--text-color-highlight: #ffffff;
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
html {
|
||||
font-family: system-ui, sans-serif;
|
||||
font-weight: normal;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: start;
|
||||
align-items: start;
|
||||
color: var(--text-color);
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
background-blend-mode: darken;
|
||||
background-color: rgba(0, 0, 0, 0.65);
|
||||
background-attachment: fixed;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: none;
|
||||
border-bottom: 1px solid var(--text-color);
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.text-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
nav {
|
||||
padding-block: 0.5rem;
|
||||
background-color: #232323;
|
||||
width: 2rem;
|
||||
height: 150vh;
|
||||
display: flex;
|
||||
position: fixed;
|
||||
flex-direction: column;
|
||||
justify-content: start;
|
||||
padding-top: 10%;
|
||||
overflow: clip;
|
||||
}
|
||||
|
||||
nav a {
|
||||
writing-mode: tb-rl;
|
||||
transform: rotate(-180deg);
|
||||
color: #cccccc;
|
||||
padding-block: 0.2rem;
|
||||
padding-inline: 0.5rem;
|
||||
transition: background-color 0.2s, color 0.2s;
|
||||
}
|
||||
|
||||
nav a.active {
|
||||
background-color: rgba(255,255,255, 0.1);
|
||||
color: var(--text-color-highlight);
|
||||
}
|
||||
|
||||
nav a.active::after {
|
||||
opacity: 1;
|
||||
background-color: var(--text-color-highlight);
|
||||
}
|
||||
|
||||
nav a::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0.1rem;
|
||||
width: 1px;
|
||||
height: 100%;
|
||||
background-color: var(--text-color);
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
|
||||
nav a:hover {
|
||||
color: white;
|
||||
}
|
||||
|
||||
nav a:hover::after {
|
||||
height: 100%;
|
||||
color: #cccccc;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
main {
|
||||
padding: 0;
|
||||
margin-left: 2rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
section {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
position: relative;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-attachment: fixed;
|
||||
background-repeat: no-repeat;
|
||||
background-color: rgba(0,0,0, 0.55);
|
||||
background-blend-mode: darken;
|
||||
}
|
||||
|
||||
article {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.bg {
|
||||
z-index: -1;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-attachment: fixed;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
#about {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-image: url("/img/bg.jpg");
|
||||
background-color: rgba(0,0,0, 0.55);
|
||||
background-blend-mode: darken;
|
||||
}
|
||||
|
||||
#about .bg {
|
||||
background-image: url("/img/lowres/bg-lowres.jpg");
|
||||
}
|
||||
|
||||
#projects {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: start;
|
||||
align-items: center;
|
||||
background-color: rgba(0,0,0, 0.85);
|
||||
background-blend-mode: darken;
|
||||
padding-top: 2rem;
|
||||
padding-bottom: 2rem;
|
||||
background-position: center;
|
||||
background-attachment: fixed;
|
||||
height: auto;
|
||||
background-image: url("/img/bg-projects.jpg");
|
||||
}
|
||||
|
||||
#projects .bg {
|
||||
background-image: url("/img/lowres/bg-projects-lowres.jpg");
|
||||
}
|
||||
|
||||
#projects .links {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding-top: 0.5rem;
|
||||
}
|
||||
|
||||
#projects .links a button {
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
border: 1px solid #fff;
|
||||
border-radius: 0.2rem;
|
||||
padding: 0.2rem;
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#projects .links a button:hover {
|
||||
background-color: rgba(255,255,255, 0.15);
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
#projects .links a button img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.tags {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 1rem;
|
||||
max-width: 18rem;
|
||||
}
|
||||
|
||||
.tags span {
|
||||
font-size: 0.65rem;
|
||||
border: 1px solid var(--text-color);
|
||||
padding: 0.2rem;
|
||||
border-radius: 0.2rem;
|
||||
cursor: default;
|
||||
user-select: none;
|
||||
transition: transform 0.2s, color 0.2s, border-color 0.2s
|
||||
}
|
||||
|
||||
.tags span:hover {
|
||||
transform: scale(1.2);
|
||||
color: var(--text-color-highlight);
|
||||
border-color: var(--text-color-highlight);
|
||||
}
|
||||
|
||||
#about article {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
#about h1 {
|
||||
color: var(--text-color-highlight);
|
||||
}
|
||||
|
||||
section h2 {
|
||||
font-size: 1.5rem;
|
||||
color: var(--text-color-highlight);
|
||||
padding-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
#projects .project-scroller {
|
||||
height: 100%;
|
||||
max-width: 100vw;
|
||||
}
|
||||
|
||||
#projects .project-scroller article {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: start;
|
||||
text-align: start;
|
||||
flex-wrap: wrap;
|
||||
max-width: 34rem;
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 1.5rem;
|
||||
padding-inline: min(1rem, 5%);
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
#projects .project-scroller article:nth-child(2n+0) {
|
||||
justify-content: end;
|
||||
flex-direction: row-reverse;
|
||||
text-align: end;
|
||||
}
|
||||
|
||||
#projects .project-scroller article .links {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
#projects .project-scroller article:nth-child(2n+0) .links {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
#projects .project-scroller article .title {
|
||||
font-size: 1.4rem;
|
||||
color: var(--text-color-highlight);
|
||||
text-align: inherit;
|
||||
}
|
||||
|
||||
#projects .project-scroller article .description {
|
||||
width: fit-content;
|
||||
flex: 1;
|
||||
min-width: 14rem;
|
||||
}
|
||||
|
||||
#projects .project-scroller article .description p {
|
||||
font-size: 0.8rem;
|
||||
color: var(--text-color);
|
||||
text-align: inherit;
|
||||
}
|
||||
|
||||
#projects .project-scroller article .project-logo {
|
||||
min-width: 9rem;
|
||||
min-height: 9rem;
|
||||
max-width: 9rem;
|
||||
max-height: 9rem;
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
#projects .project-scroller article .project-logo img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
#socials {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: rgba(0,0,0, 0.85);
|
||||
background-image: url("img/bg-social.jpg");
|
||||
background-blend-mode: darken;
|
||||
padding-top: 2rem;
|
||||
padding-bottom: 2rem;
|
||||
background-position: center;
|
||||
background-attachment: fixed;
|
||||
}
|
||||
|
||||
#socials .bg {
|
||||
background-image: url("/img/lowres/bg-social-lowres.jpg");
|
||||
}
|
||||
|
||||
#socials article {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
max-width: 28rem;
|
||||
}
|
||||
|
||||
#socials .social-link {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: var(--text-color);
|
||||
transition: all 0.2s;
|
||||
border-radius: 0.25rem;
|
||||
border: 1px solid var(--text-color);
|
||||
width: 5rem;
|
||||
height: 5rem;
|
||||
padding: 0.5rem;
|
||||
gap: 0.2rem;
|
||||
}
|
||||
|
||||
#socials .social-link:hover {
|
||||
color: var(--text-color-highlight);
|
||||
border-color: var(--text-color-highlight);
|
||||
background-color: rgba(255,255,255, 0.15);
|
||||
}
|
||||
|
||||
#socials .social-link img {
|
||||
width: 75%;
|
||||
height: 75%;
|
||||
filter: brightness(0.85);
|
||||
transition: filter 0.2s, scale 0.2s
|
||||
}
|
||||
|
||||
#socials .social-link:hover img {
|
||||
filter: brightness(1);
|
||||
scale: 1.05;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "youhavetrouble-website",
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"start": "astro dev",
|
||||
"build": "astro build",
|
||||
"preview": "astro preview",
|
||||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/mdx": "^2.0.0",
|
||||
"@astrojs/svelte": "^5.0.0",
|
||||
"astro": "^4.0.1",
|
||||
"reading-time": "^1.5.0",
|
||||
"rehype-external-links": "^3.0.0",
|
||||
"remark-gfm": "^4.0.0",
|
||||
"remark-smartypants": "^2.0.0"
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 94 KiB |
|
After Width: | Height: | Size: 135 KiB |
|
After Width: | Height: | Size: 55 KiB |
@@ -0,0 +1,93 @@
|
||||
Copyright 2016 The Merriweather Project Authors (https://github.com/EbenSorkin/Merriweather), with Reserved Font Name "Merriweather".
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
http://scripts.sil.org/OFL
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 369 B After Width: | Height: | Size: 369 B |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 719 B After Width: | Height: | Size: 719 B |
|
Before Width: | Height: | Size: 663 B After Width: | Height: | Size: 663 B |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 812 B After Width: | Height: | Size: 812 B |
|
Before Width: | Height: | Size: 705 B After Width: | Height: | Size: 705 B |
|
After Width: | Height: | Size: 99 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
@@ -0,0 +1,2 @@
|
||||
User-agent: *
|
||||
Allow: /
|
||||
@@ -1,47 +0,0 @@
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
:root {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
::-moz-selection {
|
||||
background: rgba(255,255,255, 0.2);
|
||||
}
|
||||
|
||||
::selection {
|
||||
background: rgba(255,255,255, 0.2);
|
||||
}
|
||||
|
||||
html {
|
||||
background-size: cover;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
body {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
min-height: 100vh;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
small {
|
||||
font-size: 0.6rem;
|
||||
}
|
||||
|
||||
p, h1, h2, h3, h4, h5, h6 {
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"infiniteLoopProtection": true,
|
||||
"hardReloadOnChange": false,
|
||||
"view": "browser",
|
||||
"template": "node",
|
||||
"container": {
|
||||
"port": 3000,
|
||||
"startScript": "start",
|
||||
"node": "14"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
import { ViewTransitions } from 'astro:transitions'
|
||||
import '../styles/fonts.css'
|
||||
import '../styles/global.css'
|
||||
|
||||
export interface Props {
|
||||
title: string
|
||||
description: string
|
||||
permalink: string
|
||||
}
|
||||
|
||||
const { title, description, permalink } = Astro.props
|
||||
const socialUrl = Astro.site.href + 'assets/yht_logo.png'
|
||||
---
|
||||
|
||||
<!-- Global Metadata -->
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
||||
|
||||
<!-- Primary Meta Tags -->
|
||||
<title> {title} | YouHaveTrouble's place</title>
|
||||
<meta name="title" content={title} />
|
||||
<meta name="description" content={description} />
|
||||
|
||||
<!-- Open Graph / Facebook -->
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:url" content={permalink} />
|
||||
<meta property="og:title" content={title} />
|
||||
<meta property="og:description" content={description} />
|
||||
<meta property="og:image" content={socialUrl} />
|
||||
|
||||
<!-- Twitter -->
|
||||
<meta property="twitter:card" content="summary_large_image" />
|
||||
<meta property="twitter:url" content={permalink} />
|
||||
<meta property="twitter:title" content={title} />
|
||||
<meta property="twitter:description" content={description} />
|
||||
<meta property="twitter:image" content={socialUrl} />
|
||||
|
||||
<ViewTransitions />
|
||||
|
||||
<!-- This is intentionally inlined to avoid FOUC -->
|
||||
<script is:inline>
|
||||
const root = document.documentElement
|
||||
const theme = localStorage.getItem('theme')
|
||||
if (
|
||||
theme === 'dark' ||
|
||||
(!theme && window.matchMedia('(prefers-color-scheme: dark)').matches)
|
||||
) {
|
||||
root.classList.add('theme-dark')
|
||||
} else {
|
||||
root.classList.remove('theme-dark')
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,26 @@
|
||||
<div>
|
||||
<img src="/assets/yht_logo.png" alt="YouHaveTrouble's logo">
|
||||
<p>
|
||||
Hi, I'm <strong>Paweł</strong>, also known by <strong>YouHaveTrouble</strong> on the internet.
|
||||
I'a a full-stack web developer and minecraft plugin developer.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
div {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
border-radius: 100px;
|
||||
display: block;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 1.125rem;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,19 @@
|
||||
<footer>
|
||||
<span>
|
||||
© {new Date().getFullYear()} Paweł "YouHaveTrouble" Michalewski.
|
||||
<br>
|
||||
Powered by Astro.
|
||||
</span>
|
||||
</footer>
|
||||
|
||||
<style>
|
||||
footer {
|
||||
color: var(--text-secondary);
|
||||
font-size: .8em;
|
||||
margin: 1em auto;
|
||||
max-width: 1400px;
|
||||
padding: 1em 2em;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,21 @@
|
||||
---
|
||||
import Logo from './Logo.astro'
|
||||
import Nav from './Nav.astro'
|
||||
|
||||
const { current = '' } = Astro.props;
|
||||
---
|
||||
|
||||
<style>
|
||||
header {
|
||||
display: flex;
|
||||
margin: 0 auto;
|
||||
max-width: 1400px;
|
||||
padding: 2em;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
<header>
|
||||
<Logo />
|
||||
<Nav current={current} />
|
||||
</header>
|
||||
@@ -0,0 +1,13 @@
|
||||
<style>
|
||||
|
||||
@media screen and (max-width: 520px) {
|
||||
img {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<a href="/">
|
||||
<img alt="Blog Logo" src="/assets/yht_logo.png" width="50px" height="50px" />
|
||||
</a>
|
||||
@@ -0,0 +1,65 @@
|
||||
---
|
||||
import ThemeToggleButton from './ThemeToggleButton.svelte';
|
||||
const { current = '' } = Astro.props;
|
||||
---
|
||||
|
||||
<style>
|
||||
nav {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
font-family: var(--font-family-sans);
|
||||
font-weight: 700;
|
||||
justify-content: flex-end;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
padding: 10px 5px;
|
||||
display: block;
|
||||
position: relative;
|
||||
margin-left: 20px;
|
||||
min-width: 70px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
a:not(.selected) {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
a::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
transition: transform .3s ease;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
background: var(--text-secondary);
|
||||
transform: scaleX(0);
|
||||
}
|
||||
|
||||
a:hover::before,
|
||||
.selected::before {
|
||||
transform: scaleX(1);
|
||||
}
|
||||
|
||||
.selected::before {
|
||||
background: var(--primary-color);
|
||||
}
|
||||
|
||||
.theme-toggle-container {
|
||||
width: 75px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<nav>
|
||||
<a class={current === "" ? "selected" : ""} href='/'>home</a>
|
||||
<a class={current === "about" ? "selected" : ""} href='/about'>about</a>
|
||||
<a class={current === "blog" ? "selected" : ""} href='/blog'>blog</a>
|
||||
<div class="theme-toggle-container">
|
||||
<ThemeToggleButton client:load />
|
||||
</div>
|
||||
</nav>
|
||||
@@ -0,0 +1,65 @@
|
||||
<script>
|
||||
const rootEl = typeof document !== 'undefined' ? document.documentElement : null;
|
||||
const themes = ['light', 'dark'];
|
||||
let theme = ''
|
||||
|
||||
if (typeof localStorage !== 'undefined' && localStorage.getItem('theme')) {
|
||||
theme = localStorage.getItem('theme');
|
||||
} else if (typeof window !== 'undefined' && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
theme = 'dark';
|
||||
}
|
||||
|
||||
function handleChange(event) {
|
||||
theme = event.target.value;
|
||||
localStorage.setItem('theme', theme);
|
||||
}
|
||||
|
||||
$: if (rootEl && theme === 'light') {
|
||||
rootEl.classList.remove('theme-dark');
|
||||
} else if (rootEl && theme === 'dark') {
|
||||
rootEl.classList.add('theme-dark');
|
||||
}
|
||||
|
||||
const icons = [
|
||||
`<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z"
|
||||
clip-rule="evenodd"
|
||||
/>
|
||||
</svg>`,
|
||||
`<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
>
|
||||
<path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z" />
|
||||
</svg>`,
|
||||
];
|
||||
</script>
|
||||
|
||||
|
||||
<div class="theme-toggle">
|
||||
{#each themes as t, i}
|
||||
<label class={theme === t ? 'checked' : ''}>
|
||||
{@html icons[i]}
|
||||
<input
|
||||
type="radio"
|
||||
name="theme-toggle"
|
||||
checked={theme === t}
|
||||
value={t}
|
||||
title={`Use ${t} theme`}
|
||||
aria-label={`Use ${t} theme`}
|
||||
on:change={handleChange}
|
||||
/>
|
||||
</label>
|
||||
{/each}
|
||||
</div>
|
||||
@@ -0,0 +1 @@
|
||||
/// <reference types="astro/client" />
|
||||
@@ -0,0 +1,50 @@
|
||||
---
|
||||
import BaseHead from '../components/BaseHead.astro';
|
||||
import Header from '../components/Header.astro';
|
||||
import Footer from '../components/Footer.astro';
|
||||
|
||||
export interface Props {
|
||||
title: string;
|
||||
description: string;
|
||||
permalink: string;
|
||||
current?: string;
|
||||
}
|
||||
const { title, description, permalink, current } = Astro.props;
|
||||
---
|
||||
<html lang="en">
|
||||
<head>
|
||||
<BaseHead title={title} description={description} permalink={permalink} />
|
||||
</head>
|
||||
<body>
|
||||
<div class="layout">
|
||||
<Header current={current} />
|
||||
|
||||
<main>
|
||||
<slot />
|
||||
</main>
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<style>
|
||||
.layout {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100%;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
main {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
margin: 0 auto;
|
||||
max-width: 1400px;
|
||||
padding: 1em 2em;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,51 @@
|
||||
---
|
||||
import BaseLayout from '../layouts/BaseLayout.astro';
|
||||
|
||||
const title = 'About';
|
||||
const description = 'About your blog.';
|
||||
const permalink = `${Astro.site.href}about`;
|
||||
---
|
||||
|
||||
<BaseLayout title={title} description={description} permalink={permalink} current="about">
|
||||
<div class="container">
|
||||
<h1>About me</h1>
|
||||
|
||||
<p>My name is <strong>Paweł</strong>, but I'm better known as <strong>YouHaveTrouble</strong> on the internet.</p>
|
||||
<p>
|
||||
I currently work as a full-stack web developer. Technologies I usually use for my job are javascript, vuejs,
|
||||
typescript, sql. I also often actively research and learn about new technologies that could be used to improve my
|
||||
work.
|
||||
</p>
|
||||
<p>
|
||||
In my spare time I develop plugins for minecraft servers. This is a hobby that initially made me learn how to
|
||||
code. To this day I help maintain <a href="https://purpurmc.org">Purpur</a> server software along with its
|
||||
<a href="https://modrinth.com/plugin/purpurextras">official plugin</a>. List of plugins I currently support can be
|
||||
found <a href="https://modrinth.com/user/YouHaveTrouble/plugins">here</a>.
|
||||
</p>
|
||||
<p>
|
||||
My video game interests are mostly focused on narrative heavy games, but I also enjoy some ARPGs and roguelikes.
|
||||
You can see my full steam library <a href="https://steamcommunity.com/id/YouHaveTrouble/games/?tab=all">here</a>.
|
||||
Recommendations from my favourite games would include:
|
||||
</p>
|
||||
<ul>
|
||||
<li><a href="https://store.steampowered.com/app/420530/OneShot/">OneShot</a></li>
|
||||
<li><a href="https://store.steampowered.com/app/1150690/OMORI/">OMORI</a></li>
|
||||
<li><a href="https://store.steampowered.com/app/250900/The_Binding_of_Isaac_Rebirth/">The Binding of Isaac: Rebirth</a></li>
|
||||
<li><a href="https://store.steampowered.com/app/105600/Terraria/">Terraria</a></li>
|
||||
<li><a href="https://store.steampowered.com/app/582010/Monster_Hunter_World/">Monster Hunter: World</a></li>
|
||||
<li><a href="https://store.steampowered.com/app/238960/Path_of_Exile/">Path of Exile</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</BaseLayout>
|
||||
|
||||
<style>
|
||||
ul {
|
||||
list-style-type: disc;
|
||||
padding-left: 1.5rem;
|
||||
margin-block: 0;
|
||||
}
|
||||
|
||||
ul li {
|
||||
margin-block: 0;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,60 @@
|
||||
---
|
||||
import BaseLayout from '../../layouts/BaseLayout.astro';
|
||||
import Bio from '../../components/Bio.astro';
|
||||
import getPostData from '../../utils/getPostData';
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const posts = await Astro.glob('../../data/blog-posts/*.md');
|
||||
return posts.map(p => ({
|
||||
params: { slug: p.file.split('/').pop().split('.').shift() },
|
||||
props: { post: p },
|
||||
}));
|
||||
}
|
||||
|
||||
const { Content, frontmatter } = Astro.props.post;
|
||||
const { title, description, publishDate, tags } = frontmatter;
|
||||
const { slug, readingTime } = getPostData(Astro.props.post);
|
||||
const permalink = `${Astro.site.href}blog/${slug}`;
|
||||
---
|
||||
|
||||
<BaseLayout title={title} description={description} permalink={permalink} current="blog">
|
||||
<header>
|
||||
<p>{publishDate} ~ {readingTime}</p>
|
||||
<h1>{title}</h1>
|
||||
<div class="tags" style="justify-content: center">
|
||||
{tags.map(item => (
|
||||
<span class="tag">{item}</span>
|
||||
))}
|
||||
</div>
|
||||
<hr />
|
||||
</header>
|
||||
<div class="container">
|
||||
<article class="content">
|
||||
<Content />
|
||||
</article>
|
||||
<hr />
|
||||
<Bio />
|
||||
</div>
|
||||
</BaseLayout>
|
||||
|
||||
<style>
|
||||
header {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
header h1 {
|
||||
margin-bottom: 0.7em;
|
||||
}
|
||||
|
||||
header p {
|
||||
color: var(--text-secondary);
|
||||
text-transform: uppercase;
|
||||
font-family: var(--font-family-sans);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
header hr {
|
||||
min-width: 100px;
|
||||
width: 30%;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,63 @@
|
||||
---
|
||||
import BaseLayout from '../../layouts/BaseLayout.astro';
|
||||
|
||||
const title = 'Blog';
|
||||
const description = 'Latest articles.';
|
||||
const permalink = `${Astro.site.href}blog`;
|
||||
let allPosts = [];
|
||||
try {
|
||||
allPosts = await Astro.glob('../../data/blog-posts/*.md');
|
||||
} catch (error) {
|
||||
console.error('No blog posts found');
|
||||
}
|
||||
|
||||
allPosts = allPosts.sort((a, b) => new Date(b.frontmatter.publishDate).valueOf() - new Date(a.frontmatter.publishDate).valueOf());
|
||||
---
|
||||
|
||||
<BaseLayout title={title} description={description} permalink={permalink} current="blog">
|
||||
<div class="container">
|
||||
<h1>Blog</h1>
|
||||
{allPosts.length === 0 && <p>No posts as of yet, hop back later!</p>}
|
||||
{allPosts.map((post, index) => {
|
||||
const href = `/blog/${post.file.split('/').pop().split('.').shift()}`;
|
||||
return (
|
||||
<div>
|
||||
{ index !== 0 && <hr /> }
|
||||
<div class="post-item">
|
||||
<h2>
|
||||
<a href={href}>{post.frontmatter.title}</a>
|
||||
</h2>
|
||||
<div class="tags">
|
||||
{post.frontmatter.tags.map(item => (
|
||||
<span class="tag">{item}</span>
|
||||
))}
|
||||
</div>
|
||||
<p>{post.frontmatter.description}</p>
|
||||
<div class="post-item-footer">
|
||||
<span class="post-item-date">— {post.frontmatter.publishDate}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</BaseLayout>
|
||||
|
||||
<style>
|
||||
h2,
|
||||
.post-item-footer {
|
||||
font-family: var(--font-family-sans);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.post-item-date {
|
||||
color: var(--text-secondary);
|
||||
text-align: left;
|
||||
text-transform: uppercase;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
hr {
|
||||
margin: 60px auto;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,144 @@
|
||||
---
|
||||
import BaseLayout from '../layouts/BaseLayout.astro';
|
||||
|
||||
const title = 'Home';
|
||||
const description = 'My little corner of the internet.';
|
||||
const permalink = Astro.site.href;
|
||||
---
|
||||
|
||||
<BaseLayout title={title} description={description} permalink={permalink}>
|
||||
<div class="home-container">
|
||||
<div class="home-copy">
|
||||
<h1>Welcome to my little corner of the interwebs</h1>
|
||||
<p>Feel free to check out what I got in store!</p>
|
||||
</div>
|
||||
|
||||
<div class="hero-socials-grid">
|
||||
<a href="https://github.com/YouHaveTrouble" class="social-link" target="_blank" rel="external">
|
||||
<img src="assets/icons/github.svg" alt="GitHub" draggable="false" loading="lazy">
|
||||
<span>GitHub</span>
|
||||
</a>
|
||||
<a href="https://discord.youhavetrouble.me" class="social-link" target="_blank" rel="external">
|
||||
<img src="assets/icons/discord.svg" alt="Discord" draggable="false" loading="lazy">
|
||||
<span>Discord</span>
|
||||
</a>
|
||||
<a href="https://ko-fi.com/youhavetrouble" class="social-link" target="_blank" rel="external">
|
||||
<img src="assets/icons/kofi.svg" alt="Ko-fi" draggable="false" loading="lazy">
|
||||
<span>Ko-fi</span>
|
||||
</a>
|
||||
<a href="https://steamcommunity.com/id/YouHavetrouble" class="social-link" target="_blank" rel="external">
|
||||
<img src="assets/icons/steam.svg" alt="Steam" draggable="false" loading="lazy">
|
||||
<span>Steam</span>
|
||||
</a>
|
||||
<a href="https://www.youtube.com/@YouHaveTrouble" class="social-link" target="_blank" rel="external">
|
||||
<img src="assets/icons/youtube.svg" alt="YouTube" draggable="false" loading="lazy">
|
||||
<span>YouTube</span>
|
||||
</a>
|
||||
<a href="https://modrinth.com/user/YouHaveTrouble" class="social-link" target="_blank" rel="external">
|
||||
<img src="assets/icons/modrinth.svg" alt="Modrinth" draggable="false" loading="lazy">
|
||||
<span>Modrinth</span>
|
||||
</a>
|
||||
<a href="https://wakatime.com/@YouHaveTrouble" class="social-link" target="_blank" rel="external">
|
||||
<img src="assets/icons/wakatime.svg" alt="WakaTime" draggable="false" loading="lazy">
|
||||
<span>WakaTime</span>
|
||||
</a>
|
||||
<a href="https://open.spotify.com/user/11144490753" class="social-link" target="_blank" rel="external">
|
||||
<img src="assets/icons/spotify.svg" alt="Spotify" draggable="false" loading="lazy">
|
||||
<span>Spotify</span>
|
||||
</a>
|
||||
<a href="https://www.linkedin.com/in/pawel-youhavetrouble-michalewski/" class="social-link" target="_blank" rel="external">
|
||||
<img src="assets/icons/linkedin.svg" alt="LinkedIn" draggable="false" loading="lazy">
|
||||
<span>LinkedIn</span>
|
||||
</a>
|
||||
<a href="mailto://contact@youhavetrouble.me" class="social-link" target="_blank" rel="external">
|
||||
<img src="assets/icons/email.svg" alt="Email" draggable="false" loading="lazy">
|
||||
<span>Email</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</BaseLayout>
|
||||
|
||||
<style>
|
||||
.home-container {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
justify-content: center;
|
||||
margin: 2em 0;
|
||||
min-height: 400px;
|
||||
}
|
||||
|
||||
.home-copy {
|
||||
flex: 1;
|
||||
padding: 0 1em;
|
||||
}
|
||||
|
||||
.home-copy h1 {
|
||||
font-weight: 700;
|
||||
margin-bottom: 0.5em;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.home-copy p {
|
||||
font-size: 1.4em;
|
||||
}
|
||||
|
||||
.hero-socials-grid {
|
||||
margin: 0 1em;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
max-width: min(100%, 450px);
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.hero-socials-grid a {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
width: 5.5rem;
|
||||
height: 5.5rem;
|
||||
text-decoration: none;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: transparent;
|
||||
padding: 0.5rem;
|
||||
gap: 0.25rem;
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
|
||||
.hero-socials-grid a:hover {
|
||||
color: var(--text-main);
|
||||
border-color: var(--text-main);
|
||||
}
|
||||
|
||||
html:not(.theme-dark) .hero-socials-grid a img {
|
||||
filter: invert(0.8);
|
||||
}
|
||||
|
||||
.hero-socials-grid a img {
|
||||
width: 3rem;
|
||||
height: 3rem;
|
||||
}
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
p {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 800px) {
|
||||
.home-container {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.home-copy {
|
||||
flex: 0;
|
||||
padding-bottom: 2em;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,36 @@
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Fira Sans';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url(/assets/fonts/va9B4kDNxMZdWfMOD5VnLK3eRhf6Xl7Glw.woff2)
|
||||
format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
|
||||
U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
|
||||
U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Merriweather';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(/assets/fonts/u-440qyriQwlOrhSvowK_l5-fCZMdeX3rg.woff2)
|
||||
format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
|
||||
U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
|
||||
U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Merriweather';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url(/assets/fonts/u-4n0qyriQwlOrhSvowK_l52xwNZWMf6hPvhPQ.woff2)
|
||||
format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
|
||||
U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
|
||||
U+FEFF, U+FFFD;
|
||||
}
|
||||
@@ -0,0 +1,302 @@
|
||||
:root {
|
||||
--background-body: #fff;
|
||||
--text-main: #36393b;
|
||||
--text-secondary: #6b6f72;
|
||||
--primary-color: #548e9b;
|
||||
--font-family-serif: Merriweather, serif;
|
||||
--font-family-sans: 'Fira Sans', sans-serif;
|
||||
}
|
||||
|
||||
:root.theme-dark {
|
||||
--background-body: #202122;
|
||||
--text-main: #fff;
|
||||
--text-secondary: #ccc;
|
||||
--primary-color: #548e9b;
|
||||
}
|
||||
|
||||
html {
|
||||
overflow-y: scroll;
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
p {
|
||||
text-wrap: pretty;
|
||||
}
|
||||
|
||||
@supports (scrollbar-gutter: stable) {
|
||||
html {
|
||||
overflow-y: auto;
|
||||
scrollbar-gutter: stable;
|
||||
}
|
||||
}
|
||||
|
||||
*,
|
||||
*:before,
|
||||
*:after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: var(--font-family-serif);
|
||||
font-size: 16px;
|
||||
line-height: 1.6;
|
||||
background-color: var(--background-body);
|
||||
color: var(--text-main);
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-family: var(--font-family-sans);
|
||||
font-weight: 700;
|
||||
line-height: 1.2;
|
||||
margin: 0 0 0.5em 0;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-family: var(--font-family-serif);
|
||||
font-size: 4em;
|
||||
margin: 0 0 1em 0;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin: 1.6em 0 0 0;
|
||||
font-size: 1.8em;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 1.4em;
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 1.3em;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
p,
|
||||
ul,
|
||||
ol {
|
||||
font-size: 1.3rem;
|
||||
line-height: 1.75em;
|
||||
margin: 1.2em 0;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul {
|
||||
padding-left: 2rem;
|
||||
-webkit-padding-start: 5%;
|
||||
-webkit-padding-end: 5%;
|
||||
}
|
||||
|
||||
li {
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
li p {
|
||||
margin-bottom: 0.5rem;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
transition: color linear 0.15s;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
p a {
|
||||
text-decoration: none;
|
||||
box-shadow: inset 0 -0.12em 0 var(--primary-color);
|
||||
-webkit-transition: box-shadow 0.2s ease-in-out, color 0.2s ease-in-out;
|
||||
transition: box-shadow 0.2s ease-in-out, color 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
p a:hover {
|
||||
box-shadow: inset 0 -1.5em 0 var(--primary-color);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
hr {
|
||||
padding: 0;
|
||||
border: 0;
|
||||
height: 10px;
|
||||
margin: 40px auto;
|
||||
background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg width='20' height='10' viewBox='0 0 20 10' xmlns='http://www.w3.org/2000/svg' fill-rule='evenodd' clip-rule='evenodd' stroke-miterlimit='10'%3e%3cpath fill='none' d='M0 0h20v10H0z'/%3e%3cclipPath id='a'%3e%3cpath d='M0 0h20v10H0z'/%3e%3c/clipPath%3e%3cg clip-path='url(%23a)'%3e%3cpath d='M20 7.384c-4.999-.001-5-4.768-9.999-4.768C5 2.616 5 7.384 0 7.384' fill='none' stroke-width='3' stroke='%23548E9B'/%3e%3c/g%3e%3c/svg%3e");
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: 'SF Mono', menlo, inconsolata, monospace;
|
||||
font-size: calc(1em - 2px);
|
||||
color: #555;
|
||||
padding: 0.2em 0.4em;
|
||||
border-radius: 2px;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
pre {
|
||||
border-radius: 8px !important;
|
||||
margin: 1.2em 0 !important;
|
||||
padding: 1.2em;
|
||||
}
|
||||
|
||||
pre code {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
border-left: 4px solid #cccccc;
|
||||
font-size: 1.4em;
|
||||
font-style: italic;
|
||||
margin: 2rem 0;
|
||||
padding-left: 2rem;
|
||||
padding-right: 2rem;
|
||||
}
|
||||
|
||||
blockquote p {
|
||||
padding-bottom: 6px;
|
||||
}
|
||||
|
||||
blockquote footer {
|
||||
font-size: 1.1rem;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
figure {
|
||||
padding: 0;
|
||||
border: 0;
|
||||
font-size: 100%;
|
||||
font: inherit;
|
||||
vertical-align: baseline;
|
||||
-webkit-margin-start: 0;
|
||||
-webkit-margin-end: 0;
|
||||
margin: 0 0 3em 0;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
font-family: var(--font-family-sans);
|
||||
font-size: 1.125em;
|
||||
margin: 2em 0;
|
||||
}
|
||||
|
||||
th {
|
||||
border-bottom: 2px solid #cccccc;
|
||||
padding: 0.4em 0.8em;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 0.4em 0.8em;
|
||||
}
|
||||
|
||||
.container {
|
||||
margin: 0 auto;
|
||||
max-width: 42em;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.content h1 {
|
||||
font-size: 3em;
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
.theme-toggle {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
padding: 0.33em 0.67em;
|
||||
padding-top: 8px;
|
||||
margin-left: 10px;
|
||||
gap: 0.6em;
|
||||
border-radius: 99em;
|
||||
background-color: var(--theme-code-inline-bg);
|
||||
}
|
||||
|
||||
.theme-toggle > label:focus-within {
|
||||
outline: 2px solid transparent;
|
||||
box-shadow: 0 0 0 0.08em var(--theme-accent), 0 0 0 0.12em white;
|
||||
}
|
||||
|
||||
.theme-toggle > label {
|
||||
color: var(--theme-code-inline-text);
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
opacity: 0.5;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.theme-toggle .checked {
|
||||
color: var(--theme-accent);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
input[name='theme-toggle'] {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.25rem;
|
||||
padding-block: 0.2rem;
|
||||
}
|
||||
|
||||
span.tag {
|
||||
padding: 0.25rem;
|
||||
border-radius: 0.5rem;
|
||||
font-size: 0.8rem;
|
||||
text-transform: lowercase;
|
||||
}
|
||||
|
||||
span.tag::before {
|
||||
content: '#';
|
||||
}
|
||||
|
||||
@media (max-width: 1020px) {
|
||||
h1 {
|
||||
font-size: 3em;
|
||||
}
|
||||
|
||||
.content h1 {
|
||||
font-size: 2.4em;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
body {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
p,
|
||||
ul,
|
||||
ol {
|
||||
font-size: 1.2rem;
|
||||
margin: 1em 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import readingTime from 'reading-time'
|
||||
|
||||
type Post = {
|
||||
title: string
|
||||
file: string
|
||||
rawContent: () => string
|
||||
}
|
||||
|
||||
export default function getPostData(post: Post) {
|
||||
return {
|
||||
slug: post.file.split('/').pop().split('.').shift(),
|
||||
readingTime: readingTime(post.rawContent()).text,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
// Enable top-level await, and other modern ESM features.
|
||||
"target": "ESNext",
|
||||
"module": "ESNext",
|
||||
// Enable node-style module resolution, for things like npm package imports.
|
||||
"moduleResolution": "node",
|
||||
// Enable JSON imports.
|
||||
"resolveJsonModule": true,
|
||||
// Enable stricter transpilation for better output.
|
||||
"isolatedModules": true,
|
||||
// Astro will directly run your TypeScript code, no transpilation needed.
|
||||
"noEmit": true
|
||||
}
|
||||
}
|
||||