UPDATE
This commit is contained in:
56
src/apps/menu.tsx
Normal file
56
src/apps/menu.tsx
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
import { useMemo } from "react";
|
||||||
|
|
||||||
|
export type MenuProps = {
|
||||||
|
items: MenuItem[];
|
||||||
|
basename?: string;
|
||||||
|
};
|
||||||
|
export type MenuItem = {
|
||||||
|
id: string;
|
||||||
|
data: {
|
||||||
|
title: string;
|
||||||
|
tags: string[];
|
||||||
|
hideInMenu?: boolean;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export const Menu = (props: MenuProps) => {
|
||||||
|
const { items, basename = '' } = props;
|
||||||
|
const list = useMemo(() => {
|
||||||
|
return items.filter(item => !item.data?.hideInMenu);
|
||||||
|
}, [items]);
|
||||||
|
if (list.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<nav className='flex-1 overflow-y-auto scrollbar bg-sidebar border border-sidebar-border rounded-lg p-4 shadow-sm'>
|
||||||
|
<h2 className="text-sm font-semibold text-sidebar-foreground">列表</h2>
|
||||||
|
<div className="space-y-1">
|
||||||
|
{list.map(item => (
|
||||||
|
<a
|
||||||
|
key={item.id}
|
||||||
|
href={`${basename}/docs/${item.id}/`}
|
||||||
|
className="group block rounded-md hover:bg-sidebar-accent transition-all duration-200 ease-in-out"
|
||||||
|
>
|
||||||
|
<div className="px-3 py-2.5">
|
||||||
|
<h3 className="text-sm font-semibold text-sidebar-foreground group-hover:text-sidebar-accent-foreground transition-colors">
|
||||||
|
{item.data?.title}
|
||||||
|
</h3>
|
||||||
|
{item.data?.tags && item.data.tags.length > 0 && (
|
||||||
|
<div className="flex flex-wrap gap-1.5 mt-2">
|
||||||
|
{item.data.tags.map(tag => (
|
||||||
|
<span
|
||||||
|
key={tag}
|
||||||
|
className="text-xs px-2 py-0.5 rounded-full bg-muted/60 text-muted-foreground font-medium hover:bg-muted transition-colors"
|
||||||
|
>
|
||||||
|
{tag}
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -12,6 +12,11 @@ const docs = defineCollection({
|
|||||||
// pubDate: z.coerce.date(),
|
// pubDate: z.coerce.date(),
|
||||||
createdAt: z.coerce.date().optional(),
|
createdAt: z.coerce.date().optional(),
|
||||||
updatedAt: z.coerce.date().optional(),
|
updatedAt: z.coerce.date().optional(),
|
||||||
|
showMenu: z.boolean().optional().default(true),
|
||||||
|
/**
|
||||||
|
* 在侧边栏隐藏该文档
|
||||||
|
*/
|
||||||
|
hideInMenu: z.boolean().optional().default(false),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
8
src/data/docs/menu.md
Normal file
8
src/data/docs/menu.md
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
title: 'astro 概览'
|
||||||
|
tags: ['astro', 'simple', 'template']
|
||||||
|
createdAt: '2025-11-25 20:00:00'
|
||||||
|
hideInMenu: true
|
||||||
|
---
|
||||||
|
|
||||||
|
## 概览
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
---
|
---
|
||||||
title: 'astro 例子'
|
title: 'astro 例子'
|
||||||
tags: ['astro', 'simple', 'template']
|
tags: ['astro', 'simple', 'template']
|
||||||
|
createdAt: '2025-11-25 20:00:00'
|
||||||
|
hideInMenu: true
|
||||||
---
|
---
|
||||||
|
|
||||||
## astro-simplate-template
|
## astro-simplate-template
|
||||||
|
|||||||
@@ -5,29 +5,34 @@ export interface Props {
|
|||||||
import '../styles/global.css';
|
import '../styles/global.css';
|
||||||
import '../styles/theme.css';
|
import '../styles/theme.css';
|
||||||
import 'github-markdown-css/github-markdown-light.css';
|
import 'github-markdown-css/github-markdown-light.css';
|
||||||
|
import { Menu, MenuItem } from '../apps/menu';
|
||||||
export interface Props {
|
export interface Props {
|
||||||
title?: string;
|
title?: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
lang?: string;
|
lang?: string;
|
||||||
charset?: string;
|
charset?: string;
|
||||||
|
showMenu?: boolean;
|
||||||
|
menu?: MenuItem[];
|
||||||
|
basename?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { title = 'Light Code', description = 'A lightweight code editor', lang = 'zh-CN', charset = 'UTF-8' } = Astro.props;
|
const {
|
||||||
|
title = 'Light Code',
|
||||||
|
description = 'A lightweight code editor',
|
||||||
|
lang = 'zh-CN',
|
||||||
|
charset = 'UTF-8',
|
||||||
|
showMenu = true,
|
||||||
|
menu,
|
||||||
|
basename = '',
|
||||||
|
} = Astro.props;
|
||||||
---
|
---
|
||||||
|
|
||||||
<html lang='zh-CN'>
|
<html lang={lang}>
|
||||||
<head>
|
<head>
|
||||||
<meta charset='UTF-8' />
|
<meta charset={charset} />
|
||||||
<meta name='viewport' content='width=device-width, initial-scale=1.0' />
|
<meta name='viewport' content='width=device-width, initial-scale=1.0' />
|
||||||
<title>Docs</title>
|
<title>{title}</title>
|
||||||
<link
|
<meta name='description' content={description} />
|
||||||
rel='stylesheet'
|
|
||||||
href='https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/5.8.1/github-markdown-light.min.css'
|
|
||||||
integrity='sha512-X175XRJAO6PHAUi8AA7GP8uUF5Wiv+w9bOi64i02CHKDQBsO1yy0jLSKaUKg/NhRCDYBmOLQCfKaTaXiyZlLrw=='
|
|
||||||
crossorigin='anonymous'
|
|
||||||
referrerpolicy='no-referrer'
|
|
||||||
/>
|
|
||||||
<style>
|
<style>
|
||||||
html,
|
html,
|
||||||
body {
|
body {
|
||||||
@@ -37,25 +42,29 @@ const { title = 'Light Code', description = 'A lightweight code editor', lang =
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
body {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body class='flex flex-col items-center bg-background'>
|
||||||
<div>
|
<div class='w-full'>
|
||||||
<slot name='header' />
|
<slot name='header' />
|
||||||
</div>
|
</div>
|
||||||
<main class='p-2 flex-1 overflow-hidden'>
|
<main class='flex-1 flex overflow-hidden w-full max-w-7xl px-4 py-4'>
|
||||||
<div class='markdown-body h-full scrollbar border-gray-200 overflow-auto px-6 py-2 w-[800px] border my-4 rounded-md shadow-md'>
|
{
|
||||||
|
showMenu && (
|
||||||
|
<aside class='w-64 min-w-64 h-full flex flex-col'>
|
||||||
|
<Menu items={menu!} client:only basename={basename} />
|
||||||
|
</aside>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
<div class='flex-1 h-full flex items-start justify-center overflow-hidden'>
|
||||||
|
<article class='markdown-body h-full scrollbar overflow-auto px-8 py-6 w-full max-w-4xl border border-border rounded-lg shadow-sm bg-card'>
|
||||||
<slot />
|
<slot />
|
||||||
|
</article>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
<footer>
|
<footer class='w-full border-t border-border bg-card/50 backdrop-blur-sm'>
|
||||||
<slot name='footer'>
|
<slot name='footer'>
|
||||||
<p>Copyrignt © 2025</p>
|
<div class='text-center text-sm text-muted-foreground py-4'>Copyright © 2025</div>
|
||||||
</slot>
|
</slot>
|
||||||
</footer>
|
</footer>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -1,23 +1,31 @@
|
|||||||
---
|
---
|
||||||
import { getCollection, render } from 'astro:content';
|
import { getCollection, render } from 'astro:content';
|
||||||
import Main from '@/layouts/mdx.astro';
|
import Main from '@/layouts/mdx.astro';
|
||||||
|
import { basename } from '@/modules/basename';
|
||||||
// 1. 为每个集合条目生成一个新路径
|
// 1. 为每个集合条目生成一个新路径
|
||||||
export async function getStaticPaths() {
|
export async function getStaticPaths() {
|
||||||
const posts = await getCollection('docs');
|
const posts = await getCollection('docs');
|
||||||
return posts.map((post) => ({
|
return posts.map((post) => ({
|
||||||
params: { id: post.id },
|
params: { id: post.id },
|
||||||
props: { post },
|
props: { post },
|
||||||
|
data: post,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
type Post = {
|
type Post = {
|
||||||
data: { title: string };
|
data: { title: string; tags: string[]; showMenu?: boolean };
|
||||||
};
|
};
|
||||||
// 2. 对于你的模板,你可以直接从 prop 获取条目
|
// 2. 对于你的模板,你可以直接从 prop 获取条目
|
||||||
const { post } = Astro.props as { post: Post };
|
const { post } = Astro.props as { post: Post };
|
||||||
const { Content } = await render(post);
|
const { Content } = await render(post);
|
||||||
|
console.log('post', post);
|
||||||
|
const showMenu = post.data?.showMenu;
|
||||||
|
const staticPaths = await getStaticPaths();
|
||||||
|
const menu = staticPaths.map((item) => item.data);
|
||||||
---
|
---
|
||||||
|
|
||||||
<Main>
|
<Main showMenu={showMenu} menu={menu} basename={basename}>
|
||||||
<!-- <h1 slot={'header'}>{post.data.title}</h1> -->
|
|
||||||
<Content />
|
<Content />
|
||||||
|
<div slot='menu'>
|
||||||
|
<div>sdfsdfsdf sfsdfsdf</div>
|
||||||
|
</div>
|
||||||
</Main>
|
</Main>
|
||||||
|
|||||||
Reference in New Issue
Block a user