Compare commits

..

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

15 changed files with 33 additions and 113 deletions

View file

@ -19,26 +19,16 @@
let fuse; let fuse;
let posts = []; let posts = [];
let searchInitialized = false;
async function initializeSearch() { async function initializeSearch() {
// Prevent multiple initializations const response = await fetch('/search-index.json');
if (searchInitialized) return; posts = await response.json();
try {
// Fetch the search index fuse = new Fuse(posts, {
const response = await fetch('/search-index.json'); keys: ['title', 'description', 'content'],
posts = await response.json(); threshold: 0.3,
includeMatches: true
fuse = new Fuse(posts, { });
keys: ['title', 'description', 'content'],
threshold: 0.3,
includeMatches: true
});
searchInitialized = true;
document.getElementById('search-results').innerHTML = '';
} catch (error) {
console.error('Error fetching search index:', error);
}
} }
function performSearch(query) { function performSearch(query) {
@ -47,8 +37,6 @@
return; return;
} }
if (!searchInitialized) return;
const results = fuse.search(query); const results = fuse.search(query);
const resultsElement = document.getElementById('search-results'); const resultsElement = document.getElementById('search-results');
@ -70,27 +58,14 @@
resultsElement.innerHTML = html; resultsElement.innerHTML = html;
} }
// Initialize search when the component mounts
initializeSearch();
// Add event listener for search input // Add event listener for search input
const searchInput = document.getElementById('search-input'); const searchInput = document.getElementById('search-input');
// Initialize search only when the input is focused or clicked
searchInput.addEventListener('focus', initializeSearch);
searchInput.addEventListener('click', initializeSearch);
searchInput.addEventListener('input', (e) => { searchInput.addEventListener('input', (e) => {
if (!searchInitialized) { performSearch(e.target.value);
initializeSearch().then(() => {
performSearch(e.target.value);
});
} else {
performSearch(e.target.value);
}
});
searchInput.addEventListener('focus', () => {
if (!searchInitialized) {
document.getElementById('search-results').innerHTML = '<p>Loading search index...</p>';
}
}); });
</script> </script>

View file

@ -1,6 +1,6 @@
import { z } from 'astro:content'; import { z } from 'astro:content';
export const posts = z.object({ export const blogs = z.object({
title: z.string(), title: z.string(),
description: z.string(), description: z.string(),
pubDate: z.coerce.date(), pubDate: z.coerce.date(),

View file

@ -1,17 +1,11 @@
import { defineCollection } from 'astro:content'; import { defineCollection } from 'astro:content';
import { posts } from './posts/_schemas'; import { blogs } from './blog/_schemas';
import { pages } from "./pages/_schemas";
const blogCollection = defineCollection({ const blogCollection = defineCollection({
type: 'content', type: 'content',
schema: posts, schema: blogs,
});
const pageCollection = defineCollection({
type: 'content',
schema: pages,
}); });
export const collections = { export const collections = {
'posts': blogCollection, 'blog': blogCollection,
'pages': pageCollection,
}; };

View file

@ -1,7 +0,0 @@
import { z } from 'astro:content';
export const pages = z.object({
title: z.string(),
description: z.string(),
heroImage: z.string().optional()
});

View file

@ -1,5 +0,0 @@
---
title: 'Test Page'
description: 'This is a test page'
---
testestestest

View file

@ -1,21 +0,0 @@
---
import Layout from '../layouts/Layout.astro';
import { getCollection } from "astro:content";
export async function getStaticPaths() {
const pageEntries = await getCollection('pages');
return pageEntries.map(entry => ({
params: { slug: entry.slug }, props: { entry },
}));
}
const { entry } = Astro.props;
const { Content } = await entry.render();
---
<Layout title={`${entry.data.title} | Terminal Blog`} path={`/var/log/${entry.slug}`}>
<h1 class="post-title">{entry.data.title}</h1>
<div class="post-content">
<Content/>
</div>
</Layout>

View file

@ -2,7 +2,7 @@
import Layout from '../layouts/Layout.astro'; import Layout from '../layouts/Layout.astro';
import { getCollection } from 'astro:content'; import { getCollection } from 'astro:content';
const posts = await getCollection('posts'); const posts = await getCollection('blog');
posts.sort((a, b) => new Date(b.data.pubDate).getTime() - new Date(a.data.pubDate).getTime()); posts.sort((a, b) => new Date(b.data.pubDate).getTime() - new Date(a.data.pubDate).getTime());
--- ---
@ -18,7 +18,7 @@ posts.sort((a, b) => new Date(b.data.pubDate).getTime() - new Date(a.data.pubDat
{posts.map((post) => ( {posts.map((post) => (
<p> <p>
<span style="color: var(--terminal-yellow);">{new Date(post.data.pubDate).toISOString().split('T')[0]}</span> <span style="color: var(--terminal-yellow);">{new Date(post.data.pubDate).toISOString().split('T')[0]}</span>
<a href={`/post/${post.slug}`}>{post.data.title}</a> <a href={`/blog/${post.slug}`}>{post.data.title}</a>
</p> </p>
))} ))}

View file

@ -3,7 +3,7 @@ import Layout from '../../layouts/Layout.astro';
import { getCollection } from 'astro:content'; import { getCollection } from 'astro:content';
export async function getStaticPaths() { export async function getStaticPaths() {
const blogEntries = await getCollection('posts'); const blogEntries = await getCollection('blog');
return blogEntries.map(entry => ({ return blogEntries.map(entry => ({
params: { slug: entry.slug }, props: { entry }, params: { slug: entry.slug }, props: { entry },
})); }));

View file

@ -1,25 +0,0 @@
import { getCollection } from 'astro:content';
export const prerender = true;
export async function getStaticPaths() {
const blogEntries = await getCollection('posts');
return blogEntries.map(entry => ({
params: { slug: entry.slug }, props: { entry },
}));
}
export async function GET({ props }) {
const { entry } = props;
// Format the content as plain text
const title = entry.data.title;
const date = entry.data.pubDate.toISOString().split('T')[0];
const content = entry.body;
// Combine the post info and body into a single text file
const textContent = `Title: ${title}\nPublished at: ${date}\n\n${content}`;
return new Response(textContent, {
headers: {
'Content-Type': 'text/plain',
},
});
}

View file

@ -21,7 +21,7 @@ export async function GET(context) {
const container = await AstroContainer.create({ renderers }); const container = await AstroContainer.create({ renderers });
// Load the content collection entries to add to our RSS feed. // Load the content collection entries to add to our RSS feed.
const posts = (await getCollection("posts")).sort((a, b) => const posts = (await getCollection("blog")).sort((a, b) =>
// Sort by publication date descending. // Sort by publication date descending.
a.data.pubDate > b.data.pubDate ? -1 : 1 a.data.pubDate > b.data.pubDate ? -1 : 1
); );

View file

@ -1,7 +1,7 @@
import { getCollection } from 'astro:content'; import { getCollection } from 'astro:content';
export async function GET() { export async function GET() {
const posts = await getCollection('posts'); const posts = await getCollection('blog');
const searchIndex = posts.map(post => ({ const searchIndex = posts.map(post => ({
title: post.data.title, title: post.data.title,
description: post.data.description, description: post.data.description,

View file

@ -13,7 +13,7 @@
} }
/* Light theme */ /* Light theme */
@media (prefers-color-scheme: light) { @media (prefers-color-scheme: light) {
:root:not([data-theme="dark"]) { :root {
--bg-color: #f3f4f6; --bg-color: #f3f4f6;
--text-color: #374151; --text-color: #374151;
--accent-color: #3b82f6; --accent-color: #3b82f6;
@ -23,6 +23,16 @@
--terminal-yellow: #d97706; --terminal-yellow: #d97706;
--terminal-red: #dc2626; --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) */ /* Light theme override (for switch) */
:root[data-theme="light"] { :root[data-theme="light"] {
@ -36,7 +46,6 @@
--terminal-red: #dc2626; --terminal-red: #dc2626;
} }
*, *::before, *::after { *, *::before, *::after {
box-sizing: border-box; box-sizing: border-box;
margin: 0; margin: 0;