Compare commits

..

No commits in common. "350f6f386517cf44435e9248b2f2e12517cae5c2" and "1cf002b8b8b8e14e48f878d03f82cad17ab70c13" have entirely different histories.

8 changed files with 46 additions and 291 deletions

View file

@ -1,24 +1,16 @@
import { defineConfig } from 'astro/config'; import { defineConfig } from 'astro/config';
import sitemap from '@astrojs/sitemap';
import mdx from '@astrojs/mdx';
export default defineConfig({ export default defineConfig({
site: 'https://terminal-blog.example.com', site: 'https://terminal-blog.example.com',
base: '/', base: '/',
trailingSlash: 'ignore', trailingSlash: 'ignore',
build: { build: {
format: 'directory' format: 'directory'
}, },
markdown: { markdown: {
shikiConfig: { shikiConfig: {
theme: 'nord', theme: 'nord',
wrap: true wrap: true
} }
}, }
integrations: [sitemap(), mdx()]
}); });

View file

@ -13,7 +13,6 @@
"dependencies": { "dependencies": {
"@astrojs/mdx": "^4.2.6", "@astrojs/mdx": "^4.2.6",
"@astrojs/rss": "^4.0.1", "@astrojs/rss": "^4.0.1",
"@astrojs/sitemap": "^3.3.1",
"astro": "^5.2.5", "astro": "^5.2.5",
"fuse.js": "^7.0.0", "fuse.js": "^7.0.0",
"ultrahtml": "^1.6.0" "ultrahtml": "^1.6.0"

51
pnpm-lock.yaml generated
View file

@ -14,9 +14,6 @@ importers:
'@astrojs/rss': '@astrojs/rss':
specifier: ^4.0.1 specifier: ^4.0.1
version: 4.0.11 version: 4.0.11
'@astrojs/sitemap':
specifier: ^3.3.1
version: 3.3.1
astro: astro:
specifier: ^5.2.5 specifier: ^5.2.5
version: 5.7.10(@types/node@22.15.3)(rollup@4.40.1)(typescript@5.8.3) version: 5.7.10(@types/node@22.15.3)(rollup@4.40.1)(typescript@5.8.3)
@ -55,9 +52,6 @@ packages:
'@astrojs/rss@4.0.11': '@astrojs/rss@4.0.11':
resolution: {integrity: sha512-3e3H8i6kc97KGnn9iaZBJpIkdoQi8MmR5zH5R+dWsfCM44lLTszOqy1OBfGGxDt56mpQkYVtZJWoxMyWuUZBfw==} resolution: {integrity: sha512-3e3H8i6kc97KGnn9iaZBJpIkdoQi8MmR5zH5R+dWsfCM44lLTszOqy1OBfGGxDt56mpQkYVtZJWoxMyWuUZBfw==}
'@astrojs/sitemap@3.3.1':
resolution: {integrity: sha512-GRnDUCTviBSNfXJ0Jmur+1/C+z3g36jy79VyYggfe1uNyEYSTcmAfTTCmbytrRvJRNyJJnSfB/77Gnm9PiXRRg==}
'@astrojs/telemetry@3.2.1': '@astrojs/telemetry@3.2.1':
resolution: {integrity: sha512-SSVM820Jqc6wjsn7qYfV9qfeQvePtVc1nSofhyap7l0/iakUKywj3hfy3UJAOV4sGV4Q/u450RD4AaCaFvNPlg==} resolution: {integrity: sha512-SSVM820Jqc6wjsn7qYfV9qfeQvePtVc1nSofhyap7l0/iakUKywj3hfy3UJAOV4sGV4Q/u450RD4AaCaFvNPlg==}
engines: {node: ^18.17.1 || ^20.3.0 || >=22.0.0} engines: {node: ^18.17.1 || ^20.3.0 || >=22.0.0}
@ -506,15 +500,9 @@ packages:
'@types/nlcst@2.0.3': '@types/nlcst@2.0.3':
resolution: {integrity: sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA==} resolution: {integrity: sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA==}
'@types/node@17.0.45':
resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==}
'@types/node@22.15.3': '@types/node@22.15.3':
resolution: {integrity: sha512-lX7HFZeHf4QG/J7tBZqrCAXwz9J5RD56Y6MpP0eJkka8p+K0RY/yBTW7CYFJ4VGCclxqOLKmiGP5juQc6MKgcw==} resolution: {integrity: sha512-lX7HFZeHf4QG/J7tBZqrCAXwz9J5RD56Y6MpP0eJkka8p+K0RY/yBTW7CYFJ4VGCclxqOLKmiGP5juQc6MKgcw==}
'@types/sax@1.2.7':
resolution: {integrity: sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==}
'@types/unist@2.0.11': '@types/unist@2.0.11':
resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==}
@ -553,9 +541,6 @@ packages:
resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
engines: {node: '>= 8'} engines: {node: '>= 8'}
arg@5.0.2:
resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==}
argparse@2.0.1: argparse@2.0.1:
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
@ -1304,9 +1289,6 @@ packages:
engines: {node: '>=18.0.0', npm: '>=8.0.0'} engines: {node: '>=18.0.0', npm: '>=8.0.0'}
hasBin: true hasBin: true
sax@1.4.1:
resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==}
semver@7.7.1: semver@7.7.1:
resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==}
engines: {node: '>=10'} engines: {node: '>=10'}
@ -1325,11 +1307,6 @@ packages:
sisteransi@1.0.5: sisteransi@1.0.5:
resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==}
sitemap@8.0.0:
resolution: {integrity: sha512-+AbdxhM9kJsHtruUF39bwS/B0Fytw6Fr1o4ZAIAEqA6cke2xcoO2GleBw9Zw7nRzILVEgz7zBM5GiTJjie1G9A==}
engines: {node: '>=14.0.0', npm: '>=6.0.0'}
hasBin: true
smol-toml@1.3.4: smol-toml@1.3.4:
resolution: {integrity: sha512-UOPtVuYkzYGee0Bd2Szz8d2G3RfMfJ2t3qVdZUAozZyAk+a0Sxa+QKix0YCwjL/A1RR0ar44nCxaoN9FxdJGwA==} resolution: {integrity: sha512-UOPtVuYkzYGee0Bd2Szz8d2G3RfMfJ2t3qVdZUAozZyAk+a0Sxa+QKix0YCwjL/A1RR0ar44nCxaoN9FxdJGwA==}
engines: {node: '>= 18'} engines: {node: '>= 18'}
@ -1345,9 +1322,6 @@ packages:
space-separated-tokens@2.0.2: space-separated-tokens@2.0.2:
resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
stream-replace-string@2.0.0:
resolution: {integrity: sha512-TlnjJ1C0QrmxRNrON00JvaFFlNh5TTG00APw23j74ET7gkQpTASi6/L2fuiav8pzK715HXtUeClpBTw2NPSn6w==}
string-width@4.2.3: string-width@4.2.3:
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
engines: {node: '>=8'} engines: {node: '>=8'}
@ -1704,12 +1678,6 @@ snapshots:
fast-xml-parser: 4.5.3 fast-xml-parser: 4.5.3
kleur: 4.1.5 kleur: 4.1.5
'@astrojs/sitemap@3.3.1':
dependencies:
sitemap: 8.0.0
stream-replace-string: 2.0.0
zod: 3.24.3
'@astrojs/telemetry@3.2.1': '@astrojs/telemetry@3.2.1':
dependencies: dependencies:
ci-info: 4.2.0 ci-info: 4.2.0
@ -2063,16 +2031,10 @@ snapshots:
dependencies: dependencies:
'@types/unist': 3.0.3 '@types/unist': 3.0.3
'@types/node@17.0.45': {}
'@types/node@22.15.3': '@types/node@22.15.3':
dependencies: dependencies:
undici-types: 6.21.0 undici-types: 6.21.0
'@types/sax@1.2.7':
dependencies:
'@types/node': 22.15.3
'@types/unist@2.0.11': {} '@types/unist@2.0.11': {}
'@types/unist@3.0.3': {} '@types/unist@3.0.3': {}
@ -2100,8 +2062,6 @@ snapshots:
normalize-path: 3.0.0 normalize-path: 3.0.0
picomatch: 2.3.1 picomatch: 2.3.1
arg@5.0.2: {}
argparse@2.0.1: {} argparse@2.0.1: {}
aria-query@5.3.2: {} aria-query@5.3.2: {}
@ -3383,8 +3343,6 @@ snapshots:
'@rollup/rollup-win32-x64-msvc': 4.40.1 '@rollup/rollup-win32-x64-msvc': 4.40.1
fsevents: 2.3.3 fsevents: 2.3.3
sax@1.4.1: {}
semver@7.7.1: {} semver@7.7.1: {}
sharp@0.33.5: sharp@0.33.5:
@ -3432,13 +3390,6 @@ snapshots:
sisteransi@1.0.5: {} sisteransi@1.0.5: {}
sitemap@8.0.0:
dependencies:
'@types/node': 17.0.45
'@types/sax': 1.2.7
arg: 5.0.2
sax: 1.4.1
smol-toml@1.3.4: {} smol-toml@1.3.4: {}
source-map-js@1.2.1: {} source-map-js@1.2.1: {}
@ -3447,8 +3398,6 @@ snapshots:
space-separated-tokens@2.0.2: {} space-separated-tokens@2.0.2: {}
stream-replace-string@2.0.0: {}
string-width@4.2.3: string-width@4.2.3:
dependencies: dependencies:
emoji-regex: 8.0.0 emoji-regex: 8.0.0

View file

@ -1,27 +0,0 @@
---
---
<button id="toTopBtn" title="Go to top">Top</button>
<script>
// Get the button
let toTopButton = document.getElementById("toTopBtn");
// When the user scrolls down from the top of the document, show the button
window.addEventListener("scroll", ()=> {
if (window.scrollY < document.documentElement.clientHeight) {
toTopButton.classList.remove('fade-in');
toTopButton.classList.add('fade-out');
toTopButton.style.display = 'block';
} else {
toTopButton.classList.remove('fade-out');
toTopButton.classList.remove('fade-in');
}
})
// When the user clicks on the button, scroll to the top of the document
toTopButton.addEventListener("click", toTop);
function toTop() {
document.body.scrollTop = 0;
document.documentElement.scrollTop = 0;
}
</script>

View file

@ -1,119 +1,22 @@
--- ---
--- ---
<div class="theme-dropdown" id="theme-dropdown"> <button class="theme-switcher" id="theme-switcher">
<button class="theme-switcher" id="theme-switcher">Theme</button> Toggle Theme
<div class="menu-body" id="menu-body"> </button>
<div class="dropdown-item" data-theme="auto">System</div>
<div class="dropdown-item" data-theme="dark">Dark</div>
<div class="dropdown-item" data-theme="light">Light</div>
</div>
</div>
<style>
.theme-dropdown {
position: relative;
display: inline-block;
}
.menu-body {
display: none;
position: fixed;
right: 45px;
bottom: 70px;
background-color: var(--bg-color);
border: 1px solid var(--border-color);
min-width: 140px;
z-index: 20;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
}
.dropdown-item {
padding: 0.5rem 1rem;
cursor: pointer;
transition: background-color 0.2s ease;
}
.dropdown-item:hover {
background-color: var(--border-color);
}
.dropdown-item.active {
color: var(--accent-color);
font-weight: bold;
}
.theme-dropdown:hover .menu-body {
display: block;
}
</style>
<script> <script>
// Constants for theme options const themeSwitcher = document.getElementById('theme-switcher');
const THEME_AUTO = 'auto';
const THEME_DARK = 'dark';
const THEME_LIGHT = 'light';
// DOM elements
const themeDropdown = document.getElementById('theme-dropdown');
const menuBody = document.getElementById('menu-body');
const dropdownItems = document.querySelectorAll('.dropdown-item');
const root = document.documentElement; const root = document.documentElement;
// Get system preference // Check for saved theme preference or default to dark
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; const savedTheme = localStorage.getItem('theme') || 'dark';
const systemTheme = prefersDark ? THEME_DARK : THEME_LIGHT; root.setAttribute('data-theme', savedTheme);
// Get saved theme from localStorage or default to auto themeSwitcher?.addEventListener('click', () => {
const savedThemeMode = localStorage.getItem('themeMode') || THEME_AUTO; const currentTheme = root.getAttribute('data-theme');
const savedTheme = localStorage.getItem('theme'); const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
// Function to update active state in dropdown menu root.setAttribute('data-theme', newTheme);
function updateActiveState(activeTheme) { localStorage.setItem('theme', newTheme);
dropdownItems.forEach(item => {
if (item.getAttribute('data-theme') === activeTheme) {
item.classList.add('active');
} else {
item.classList.remove('active');
}
});
}
// Function to apply theme
function applyTheme(themeMode) {
// Update active state in dropdown
updateActiveState(themeMode);
// Save theme mode preference
localStorage.setItem('themeMode', themeMode);
// Apply the appropriate theme
if (themeMode === THEME_AUTO) {
// Follow system
localStorage.removeItem('theme');
root.removeAttribute('data-theme');
} else {
// Set to specific theme
root.setAttribute('data-theme', themeMode);
localStorage.setItem('theme', themeMode);
}
}
// Initialize theme
applyTheme(savedThemeMode);
// Add click handlers to dropdown items
dropdownItems.forEach(item => {
item.addEventListener('click', () => {
const selectedTheme = item.getAttribute('data-theme');
applyTheme(selectedTheme);
});
});
// Listen for system preference changes
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => {
if (savedThemeMode === THEME_AUTO) {
// Only update if we're in auto mode
root.removeAttribute('data-theme');
}
}); });
</script> </script>

View file

@ -2,7 +2,6 @@
import '../styles/global.css'; import '../styles/global.css';
import Search from '../components/Search.astro'; import Search from '../components/Search.astro';
import ThemeSwitcher from '../components/ThemeSwitcher.astro'; import ThemeSwitcher from '../components/ThemeSwitcher.astro';
import BackToTop from "../components/BackToTop.astro";
import { siteConfig } from "../config"; import { siteConfig } from "../config";
interface Props { interface Props {
@ -27,6 +26,7 @@ const { title, path = formattedPath } = Astro.props;
<title>{title}</title> <title>{title}</title>
</head> </head>
<body> <body>
<ThemeSwitcher />
<main> <main>
<div class="container"> <div class="container">
<div class="terminal-path"> <div class="terminal-path">
@ -47,10 +47,6 @@ const { title, path = formattedPath } = Astro.props;
</main> </main>
<footer class="footer"> <footer class="footer">
<div class="floating">
<BackToTop/>
<ThemeSwitcher/>
</div>
<div class="container"> <div class="container">
Powered by <a href="https://git.gb0.dev/gb/mercury"><img src="/mercury.svg" width="16px" alt="mercury logo" /> mercury</a> Powered by <a href="https://git.gb0.dev/gb/mercury"><img src="/mercury.svg" width="16px" alt="mercury logo" /> mercury</a>
</div> </div>

View file

@ -25,7 +25,16 @@ posts.sort((a, b) => new Date(b.data.pubDate).getTime() - new Date(a.data.pubDat
{posts.length === 0 && ( {posts.length === 0 && (
<> <>
<p> <p>
<span style="color: var(--terminal-yellow);">No posts here yet</span> <span style="color: var(--terminal-yellow);">2025-06-08</span>
<a href="/blog/terminal-setup">My Terminal Setup</a>
</p>
<p>
<span style="color: var(--terminal-yellow);">2025-06-05</span>
<a href="/blog/minimalism">The Art of Minimalism</a>
</p>
<p>
<span style="color: var(--terminal-yellow);">2025-06-01</span>
<a href="/blog/first-post">First Post</a>
</p> </p>
</> </>
)} )}

View file

@ -11,30 +11,7 @@
--terminal-red: #ef4444; --terminal-red: #ef4444;
--font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
} }
/* Light theme */
@media (prefers-color-scheme: light) {
:root {
--bg-color: #f3f4f6;
--text-color: #374151;
--accent-color: #3b82f6;
--border-color: #d1d5db;
--header-color: #1f2937;
--terminal-green: #059669;
--terminal-yellow: #d97706;
--terminal-red: #dc2626;
}
:root:not([data-theme="light"]) {
--bg-color: #1f2937;
--text-color: #a5b4cf;
--accent-color: #64a0ff;
--border-color: #3b4351;
--header-color: #83a2ce;
--terminal-green: #4ade80;
--terminal-yellow: #fbbf24;
--terminal-red: #ef4444;
}
}
/* Light theme override (for switch) */
:root[data-theme="light"] { :root[data-theme="light"] {
--bg-color: #f3f4f6; --bg-color: #f3f4f6;
--text-color: #374151; --text-color: #374151;
@ -139,55 +116,6 @@ main {
opacity: 0.7; opacity: 0.7;
} }
.footer img {
vertical-align: middle;
}
.footer .floating {
position: fixed;
bottom: 20px;
right: 30px;
z-index: 10;
display: flex;
flex-direction: column;
border: none;
outline: none;
padding: 15px;
}
#toTopBtn {
display: none;
background: var(--border-color);
border: none;
color: var(--text-color);
padding: 0.5rem 1rem;
font-family: var(--font-mono);
cursor: pointer;
}
#toTopBtn:hover {
background: var(--accent-color);
color: var(--bg-color);
}
/* Theme Switcher */
.theme-switcher {
background: var(--border-color);
border: none;
color: var(--text-color);
padding: 0.5rem 1rem;
font-family: var(--font-mono);
cursor: pointer;
transition: background-color 0.3s ease, color 0.3s ease;
}
.theme-switcher:hover {
background: var(--accent-color);
color: var(--bg-color);
}
/* Post styles */ /* Post styles */
.post-title { .post-title {
color: var(--header-color); color: var(--header-color);
@ -218,18 +146,24 @@ main {
opacity: 0.7; opacity: 0.7;
} }
/* helper Class */ /* Theme Switcher */
.fade-in { .theme-switcher {
opacity: 1; position: fixed;
transition-property: opacity; top: 1rem;
transition-duration: .7s; right: 1rem;
transition-timing-function: cubic-bezier(.4,0,1,1); background: var(--border-color);
border: none;
color: var(--text-color);
padding: 0.5rem 1rem;
border-radius: 4px;
font-family: var(--font-mono);
cursor: pointer;
transition: background-color 0.3s ease, color 0.3s ease;
} }
.fade-out {
opacity: 0; .theme-switcher:hover {
transition-property: opacity; background: var(--accent-color);
transition-duration: .7s; color: var(--bg-color);
transition-timing-function: cubic-bezier(.4,0,1,1);
} }
/* Media Queries */ /* Media Queries */