Notes edit and remove tests

Signed-off-by: Hadi <112569860+anotherhadi@users.noreply.github.com>
This commit is contained in:
Hadi
2026-04-25 00:07:18 +02:00
parent 294c4e3acd
commit e3f0fc5735
9 changed files with 43 additions and 290 deletions
+21 -17
View File
@@ -3,6 +3,7 @@ import { getCollection, render } from "astro:content";
import Layout from "../../layouts/Layout.astro";
import { Shield, ChevronLeft, List, PanelRight } from "@lucide/astro";
import Author from "../../components/Author.astro";
import { getCategory, extractInlineHashtags } from "../../utils/notes";
export async function getStaticPaths() {
const notes = await getCollection("notes");
@@ -17,12 +18,6 @@ const { Content } = await render(entry);
const allNotes = await getCollection("notes");
const sortedNotes = allNotes.sort((a, b) => a.data.title.localeCompare(b.data.title));
function getCategory(n: { id: string; data: { category?: string } }): string {
if (n.data.category) return n.data.category;
const parts = n.id.split("/");
return parts.length > 1 ? parts[0] : "General";
}
const categories = [...new Set(allNotes.map(getCategory))].sort();
function formatDate(date: Date) {
@@ -30,7 +25,8 @@ function formatDate(date: Date) {
}
function extractLinks(body: string): string[] {
const re = /\(\/notes\/([^)#\s]+)\)/g;
// Capture slug before optional #fragment: (/notes/slug) or (/notes/slug#section)
const re = /\(\/notes\/([^)#\s]+)(?:#[^)\s]*)?\)/g;
const ids: string[] = [];
let m;
while ((m = re.exec(body)) !== null) ids.push(m[1]);
@@ -57,22 +53,28 @@ const graphEdges = [
...backlinks.map((n) => ({ from: n.id, to: entry.id })),
];
function extractInlineHashtags(body: string): string[] {
const re = /#(\w+)/g;
const tags: string[] = [];
let m;
while ((m = re.exec(body)) !== null) tags.push(m[1].toLowerCase());
return [...new Set(tags)];
// Mirrors github-slugger exactly: keeps _, keeps unicode letters/numbers, spaces → hyphens
function slugify(text: string) {
return text
.toLowerCase()
.replace(/[^\p{L}\p{N}\s_-]/gu, "") // keep letters (unicode), numbers, spaces, _, -
.trim()
.replace(/ +/g, "-"); // spaces → hyphens (github-slugger does exactly this)
}
function slugify(text: string) {
return text.toLowerCase().replace(/`[^`]*`/g, "").replace(/[^\w\s-]/g, "").trim().replace(/[\s_]+/g, "-");
}
const headings: { depth: number; text: string; id: string }[] = [];
const headingRe = /^(#{2,4}) (.+)$/gm;
let hm;
while ((hm = headingRe.exec(entry.body ?? "")) !== null) {
const raw = hm[2].trim().replace(/\*\*|__|\*|_|`/g, "");
// Strip markdown formatting while preserving literal _ (word-internal underscores like my_var)
// Paired markers are stripped to their content; lone * are removed; _ only stripped at word boundaries
const raw = hm[2].trim()
.replace(/`[^`]*`/g, "") // `code` → remove
.replace(/\*\*(.*?)\*\*/g, "$1") // **bold** → text
.replace(/(?<!\p{L}\p{N})__(.*?)__(?!\p{L}\p{N})/gu, "$1") // __bold__ → text
.replace(/\*(.*?)\*/g, "$1") // *italic* → text
.replace(/(?<!\p{L}\p{N})_(.*?)_(?!\p{L}\p{N})/gu, "$1") // _italic_ → text
.replace(/[*]/g, ""); // orphan * markers
headings.push({ depth: hm[1].length, text: raw, id: slugify(raw) });
}
---
@@ -271,6 +273,8 @@ while ((hm = headingRe.exec(entry.body ?? "")) !== null) {
<canvas
id="note-graph"
height="190"
role="img"
aria-label="Graph of linked notes"
style="width:100%; display:block; background: oklch(2% 0 0); cursor:default;"
></canvas>
{graphNodes.length <= 1 && (