New Website in VueJS #6

Open
alice wants to merge 11 commits from new-website into main
Showing only changes of commit a7568b4f9f - Show all commits

View file

@ -1,94 +1,64 @@
<template>
<div class="min-h-screen bg-base-100 text-base-content">
<div class="container mx-auto px-4 py-8">
<div class="grid grid-cols-1 lg:grid-cols-6 gap-8">
<div class="grid grid-cols-1 lg:grid-cols-5 gap-8">
<!-- Sidebar con navigazione pagine wiki -->
<aside class="lg:col-span-1">
<nav
class="sticky top-4 bg-base-200 rounded-lg p-4 border border-base-300"
>
<h2 class="text-lg font-bold mb-4 text-primary">Wiki</h2>
<aside class="lg:col-span-1 sticky top-4">
<nav class="rounded-lg">
<!-- Lista pagine dalla sidebar -->
<div class="space-y-2 text-sm">
<div v-for="(item, index) in sidebarItems" :key="index">
<!-- Heading di sezione -->
<h3
v-if="item.type === 'heading'"
class="text-xs font-bold text-secondary uppercase mt-4 mb-2"
>
<h3 v-if="item.type === 'heading'" class="text-xs font-bold text-secondary uppercase mt-4 mb-2">
{{ item.text }}
</h3>
<!-- Link a pagina -->
<a
v-else-if="item.type === 'link'"
:href="item.isExternal ? item.url : '#'"
:target="item.isExternal ? '_blank' : null"
:rel="item.isExternal ? 'noopener noreferrer' : null"
<a v-else-if="item.type === 'link'" :href="item.isExternal ? item.url : '#'"
:target="item.isExternal ? '_blank' : null" :rel="item.isExternal ? 'noopener noreferrer' : null"
@click="onSidebarLinkClick($event, item)"
class="block py-1.5 px-2 rounded hover:bg-base-300 transition truncate"
:class="{
'bg-base-300 text-primary':
class="block py-1 px-2 rounded-lg hover:bg-base-300/20 transition truncate" :class="{
'bg-base-300/20 text-primary font-bold':
!item.isExternal && currentPage === item.slug,
}"
:title="item.text"
>
{{ item.text }}
}" :title="item.text">
{{ item.text }}<span v-if="item.isExternal" class="ml-1 text-base-content/60"></span>
</a>
<!-- TOC (Table of Contents) - Outline minimal terminal style -->
<nav v-if="currentPage === item.slug && outline.length > 0" class="sticky top-4">
<ul class="space-y-0 text-xs font-mono leading-snug border-l border-base-300 pl-3">
<li v-for="heading in outline" :key="heading.id">
<a :href="`#${heading.id}`" @click.prevent="scrollToHeading(heading.id)"
class="block py-0.5 hover:text-base-content rounded-lg transition truncate"
:style="{ paddingLeft: `${(heading.level - 1) * 0.5}rem` }" :class="{
'text-primary bg-base-300/20': activeHeading === heading.id,
'text-base-content/60': activeHeading !== heading.id,
}" :title="heading.text">
{{ heading.text }}
</a>
</li>
</ul>
</nav>
</div>
</div>
</nav>
</aside>
<!-- Contenuto principale -->
<main class="lg:col-span-5">
<main class="lg:col-span-4">
<div v-if="loading" class="text-center py-12">
<span class="text-primary"
>Loading<span class="blinking-cursor"></span
></span>
<span class="text-primary">Loading<span class="blinking-cursor"></span></span>
</div>
<article
v-else
class="bg-base-200 rounded-lg p-8 border border-base-300"
>
<article v-else class="bg-base-200 rounded-lg p-8 border border-base-300">
<h1 class="text-4xl font-bold text-primary mb-6">
{{ pageTitle }}<span class="blinking-cursor"></span>
</h1>
<div
class="markdown-content prose prose-invert max-w-none"
v-html="pageContent"
></div>
<div class="markdown-content prose prose-invert max-w-none" v-html="pageContent"></div>
Review

An icon would look better :)

An icon would look better :)
</article>
</main>
<!-- TOC (Table of Contents) - Outline minimal terminal style -->
<aside class="lg:col-span-1">
<nav v-if="outline.length > 0" class="sticky top-4">
<div class="text-xs text-secondary mb-2 font-mono">// Contents</div>
<ul
class="space-y-0 text-xs font-mono leading-snug border-l border-base-300 pl-2"
>
<li v-for="heading in outline" :key="heading.id">
<a
:href="`#${heading.id}`"
@click.prevent="scrollToHeading(heading.id)"
class="block py-0.5 hover:text-primary transition truncate"
:style="{ paddingLeft: `${(heading.level - 2) * 0.5}rem` }"
:class="{
'text-primary': activeHeading === heading.id,
'text-secondary': activeHeading !== heading.id,
}"
:title="heading.text"
>
{{ heading.text }}
</a>
</li>
</ul>
</nav>
</aside>
</div>
</div>
<button class="btn btn-circle btn-secondary bottom-4 right-4 fixed font-bold text-3xl" :class="{ 'hidden': !showScrollTopButton }" @click="scrollToTop"></button>
</div>
</template>
@ -107,6 +77,12 @@ const currentPage = ref("home");
const sidebarItems = ref([]);
const outline = ref([]);
const activeHeading = ref("");
const showScrollTopButton = ref(false);
function scrollToTop() {
window.scrollTo({ top: 0, behavior: "smooth" });
showScrollTopButton.value = false;
}
function onSidebarLinkClick(event, item) {
if (item.isExternal) return;
@ -131,7 +107,7 @@ async function loadSidebar() {
continue;
// Heading (###)
if (line.startsWith("###")) {
if (line.startsWith("###") || line.startsWith("- ###")) {
items.push({
type: "heading",
text: line.replace(/^###\s*/, "").trim(),
@ -227,7 +203,7 @@ async function loadPage(slug) {
renderer.heading = function (text, level) {
const id = text.toLowerCase().replace(/[^\w]+/g, "-");
return `<h${level} id="${id}">${text}</h${level}>`;
return `<h${level} id="${id}" href="#${id}" >${text}</h${level}>`;
};
renderer.image = function (href, title, text) {
@ -258,6 +234,7 @@ async function loadPage(slug) {
// Render e outline coerenti, entrambi senza H1 iniziale
pageContent.value = marked(contentWithoutMainTitle, { renderer });
// TODO: togliere parti di codice per elaborare l'outline
extractOutline(contentWithoutMainTitle);
} catch (error) {
console.error("Error loading page:", error);
@ -275,7 +252,7 @@ function extractOutline(markdown) {
const lines = markdown.split("\n");
for (const line of lines) {
const match = line.match(/^(#{2,4})\s+(.+)$/);
const match = line.match(/^(#{1,5})\s+(.+)$/);
if (match) {
const level = match[1].length;
const text = match[2];
@ -321,6 +298,11 @@ onMounted(async () => {
await loadPage(page);
window.addEventListener("scroll", handleScroll);
window.addEventListener("scroll", () => {
const scrollTop = window.scrollY || document.documentElement.scrollTop;
showScrollTopButton.value = scrollTop > 300;
});
});
</script>