Edit nav & add folder pages

Signed-off-by: Hadi <hadi@example.com>
This commit is contained in:
Hadi
2026-04-29 16:23:51 +02:00
parent eea8c3e9be
commit 0e83788a15
4 changed files with 249 additions and 45 deletions
+26 -16
View File
@@ -6,11 +6,7 @@ import NoteTOC from "../../components/NoteTOC.astro";
import NoteNavSidebar from "../../components/NoteNavSidebar.svelte";
import NoteGraphSidebar from "../../components/NoteGraphSidebar.astro";
import NoteVars from "../../components/NoteVars.svelte";
import {
getCategory,
extractLinks,
extractHeadings,
} from "../../utils/notes";
import { getCategory, extractLinks, extractHeadings } from "../../utils/notes";
export async function getStaticPaths() {
const notes = await getCollection("notes");
@@ -41,7 +37,11 @@ const backlinks = allNotes.filter(
const graphNodes = [
{ id: entry.id, title: entry.data.title, current: true },
...forwardLinks.map((n) => ({ id: n.id, title: n.data.title, current: false })),
...forwardLinks.map((n) => ({
id: n.id,
title: n.data.title,
current: false,
})),
...backlinks
.filter((n) => !forwardLinks.some((f) => f.id === n.id))
.map((n) => ({ id: n.id, title: n.data.title, current: false })),
@@ -72,7 +72,7 @@ const headings = extractHeadings(entry.body ?? "");
</style>
<Layout
title={`${entry.data.title} Security Notes`}
title={`${entry.data.title} - Security Notes`}
description={entry.data.description}
>
<main class="max-w-screen-2xl mx-auto">
@@ -92,12 +92,24 @@ const headings = extractHeadings(entry.body ?? "");
>
<ul>
<li>
<a
href="/notes"
class="hover:text-base-content/70"
>notes</a>
<a href="/notes" class="hover:text-base-content/70"
>notes</a
>
</li>
<li>
{
entry.id.includes("/") ? (
<a
href={`/notes/${getCategory(entry)}`}
class="hover:text-base-content/70"
>
{getCategory(entry)}
</a>
) : (
getCategory(entry)
)
}
</li>
<li>{getCategory(entry)}</li>
</ul>
</div>
<div class="flex items-center gap-2">
@@ -196,8 +208,7 @@ const headings = extractHeadings(entry.body ?? "");
<label
for="nav-drawer"
aria-label="close sidebar"
class="drawer-overlay"
></label>
class="drawer-overlay"></label>
<NoteNavSidebar
client:load
notes={sortedNotes}
@@ -212,8 +223,7 @@ const headings = extractHeadings(entry.body ?? "");
<label
for="graph-drawer"
aria-label="close sidebar"
class="drawer-overlay xl:hidden"
></label>
class="drawer-overlay xl:hidden"></label>
<NoteGraphSidebar
entry={entry}
graphNodes={graphNodes}
+178
View File
@@ -0,0 +1,178 @@
---
import { getCollection } from "astro:content";
import Layout from "../../layouts/Layout.astro";
import NoteNavSidebar from "../../components/NoteNavSidebar.svelte";
import { getCategory } from "../../utils/notes";
import { List } from "@lucide/astro";
export async function getStaticPaths() {
const notes = await getCollection("notes");
const folderCategories = [
...new Set(
notes.filter((n) => n.id.includes("/")).map((n) => getCategory(n)),
),
];
return folderCategories.map((category) => {
const allNotes = notes.sort((a, b) =>
a.data.title.localeCompare(b.data.title),
);
const categories = [...new Set(notes.map(getCategory))].sort();
return {
params: { category },
props: {
category,
categoryNotes: notes
.filter((n) => getCategory(n) === category)
.sort((a, b) => a.data.title.localeCompare(b.data.title)),
allNotes,
categories,
},
};
});
}
const { category, categoryNotes, allNotes, categories } = Astro.props;
if (!categoryNotes) {
return new Response(null, { status: 404, statusText: "Not found" });
}
---
<style>
.drawer.lg\:drawer-open > .drawer-side {
top: 3rem;
height: calc(100vh - 3rem);
}
</style>
<Layout
title={`${category} - Security Notes`}
description={`Notes on ${category}.`}
>
<main class="max-w-screen-2xl mx-auto">
<div class="drawer lg:drawer-open min-h-[calc(100vh-3rem)]">
<input id="nav-drawer" type="checkbox" class="drawer-toggle" />
<div class="drawer-content flex flex-col min-w-0">
<main class="flex-1 px-4 sm:px-6 lg:px-10 py-6 lg:py-10 min-w-0">
<div class="max-w-3xl mx-auto lg:mx-0">
<div class="flex items-center justify-between mb-10">
<div
class="breadcrumbs text-xs font-mono text-base-content/35 p-0"
>
<ul>
<li>
<a href="/notes" class="hover:text-base-content/70"
>notes</a>
</li>
<li class="text-base-content/60">{category}</li>
</ul>
</div>
<label
for="nav-drawer"
class="btn btn-ghost btn-xs lg:hidden font-mono text-base-content/40 hover:text-base-content/70 border border-base-300/50"
>
<List size={11} />
nav
</label>
</div>
<div class="mb-10">
<div class="flex items-baseline gap-3 mb-1">
<h1 class="text-4xl sm:text-5xl font-bold">
<span class="text-primary/40 font-mono mr-1">/</span>{
category
}
</h1>
</div>
<p class="font-mono text-xs text-base-content/25 ml-8">
{categoryNotes.length} note{
categoryNotes.length !== 1 ? "s" : ""
}
</p>
</div>
<div class="border-t border-base-300/40 mb-1"></div>
<ul class="divide-y divide-base-300/20">
{
categoryNotes.map((note) => (
<li>
<a
href={`/notes/${note.id}`}
class="group flex items-center gap-4 py-3 hover:bg-base-200/30 px-2 -mx-2 transition-colors"
>
<div class="flex-1 min-w-0">
<div class="flex flex-col mb-0.5">
<span class="font-semibold text-sm group-hover:text-primary transition-colors">
{note.data.title}
</span>
{note.data.description && (
<span class="text-xs text-base-content/35 truncate">
{note.data.description}
</span>
)}
</div>
{note.data.tags.length > 0 && (
<div class="flex flex-wrap gap-1 mt-1">
{note.data.tags.map((tag) => (
<span class="badge badge-ghost badge-xs font-mono text-base-content/30">
{tag}
</span>
))}
</div>
)}
</div>
<svg
xmlns="http://www.w3.org/2000/svg"
width="14"
height="14"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="text-base-content/20 group-hover:text-primary/50 shrink-0 transition-colors"
>
<path d="m9 18 6-6-6-6" />
</svg>
</a>
</li>
))
}
</ul>
<div
class="border-t border-base-300/30 mt-12 pt-6 flex items-center justify-between font-mono text-[10px] text-base-content/25"
>
<a
href="/notes"
class="hover:text-base-content/50 transition-colors"
>
← all notes
</a>
<a href="/" class="hover:text-base-content/50 transition-colors">
~/hadi
</a>
</div>
</div>
</main>
</div>
<div class="drawer-side z-50">
<label
for="nav-drawer"
aria-label="close sidebar"
class="drawer-overlay"></label>
<NoteNavSidebar
client:load
notes={allNotes}
currentCategory={category}
categories={categories}
/>
</div>
</div>
</main>
</Layout>
+1 -1
View File
@@ -22,7 +22,7 @@ const searchNotes = sortedNotes.map((n) => ({
---
<Layout
title="Security Notes Another Hadi"
title="Security Notes - Another Hadi"
description="Reference notes on cybersecurity tools and techniques."
>
<main class="max-w-4xl mx-auto px-4 py-16 sm:py-20">