初步
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
---
|
||||
import type { BlogPost } from '@/lib/posts';
|
||||
|
||||
interface Props {
|
||||
post: BlogPost;
|
||||
}
|
||||
|
||||
const { post } = Astro.props;
|
||||
---
|
||||
|
||||
<article class="post-card">
|
||||
<a href={post.href}>
|
||||
<time datetime={post.date.toISOString()}>{post.dateText}</time>
|
||||
<h2>{post.title}</h2>
|
||||
{post.summary && <p>{post.summary}</p>}
|
||||
</a>
|
||||
<div class="meta-list">
|
||||
{post.categories.map((category) => <a href={`/categories/${encodeURIComponent(category)}/`}>{category}</a>)}
|
||||
{post.tags.map((tag) => <a href={`/tags/${encodeURIComponent(tag)}/`}>#{tag}</a>)}
|
||||
</div>
|
||||
</article>
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
/// <reference path="../.astro/types.d.ts" />
|
||||
/// <reference types="astro/client" />
|
||||
@@ -0,0 +1,44 @@
|
||||
---
|
||||
import '../styles/site.css';
|
||||
|
||||
interface Props {
|
||||
title?: string;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
const siteTitle = "Bi's Blog";
|
||||
const { title = siteTitle, description = 'Personal blog by biss.' } = Astro.props;
|
||||
const pageTitle = title === siteTitle ? siteTitle : `${title} | ${siteTitle}`;
|
||||
---
|
||||
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="description" content={description} />
|
||||
<link rel="icon" href="/images/Bi.ico" />
|
||||
<title>{pageTitle}</title>
|
||||
</head>
|
||||
<body>
|
||||
<header class="site-header">
|
||||
<nav class="nav">
|
||||
<a class="brand" href="/">Bi's Blog</a>
|
||||
<div class="nav-links">
|
||||
<a href="/archives/">归档</a>
|
||||
<a href="/categories/">分类</a>
|
||||
<a href="/tags/">标签</a>
|
||||
<a href="/about/">关于</a>
|
||||
<a href="/link/">友链</a>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
<main>
|
||||
<slot />
|
||||
</main>
|
||||
<footer class="site-footer">
|
||||
<span>© {new Date().getFullYear()} Bi's Blog</span>
|
||||
<a href="/rss.xml">RSS</a>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,28 @@
|
||||
type PageModule = {
|
||||
frontmatter: Record<string, unknown>;
|
||||
Content: unknown;
|
||||
rawContent?: () => string;
|
||||
};
|
||||
|
||||
export type SitePage = PageModule & {
|
||||
title: string;
|
||||
slug: string;
|
||||
};
|
||||
|
||||
const modules = import.meta.glob<PageModule>('/source/**/index.md', { eager: true });
|
||||
|
||||
export function getSitePages(): SitePage[] {
|
||||
return Object.entries(modules)
|
||||
.filter(([path]) => {
|
||||
if (path.includes('/_posts/') || path.includes('/_drafts/')) return false;
|
||||
return !['/source/categories/index.md', '/source/tags/index.md'].includes(path);
|
||||
})
|
||||
.map(([path, module]) => {
|
||||
const slug = path.replace('/source/', '').replace('/index.md', '');
|
||||
return {
|
||||
...module,
|
||||
title: String(module.frontmatter.title ?? slug),
|
||||
slug,
|
||||
};
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
type MarkdownModule = {
|
||||
frontmatter: Record<string, unknown>;
|
||||
Content: unknown;
|
||||
rawContent?: () => string;
|
||||
file?: string;
|
||||
};
|
||||
|
||||
export type BlogPost = MarkdownModule & {
|
||||
title: string;
|
||||
slug: string;
|
||||
date: Date;
|
||||
dateText: string;
|
||||
tags: string[];
|
||||
categories: string[];
|
||||
summary: string;
|
||||
href: string;
|
||||
};
|
||||
|
||||
const modules = import.meta.glob<MarkdownModule>('/source/_posts/**/*.md', { eager: true });
|
||||
|
||||
function asArray(value: unknown): string[] {
|
||||
if (Array.isArray(value)) return value.map(String).filter(Boolean);
|
||||
if (typeof value === 'string' && value.trim()) return [value.trim()];
|
||||
return [];
|
||||
}
|
||||
|
||||
function toDate(value: unknown): Date {
|
||||
if (value instanceof Date) return value;
|
||||
if (typeof value === 'string' || typeof value === 'number') {
|
||||
const date = new Date(value);
|
||||
if (!Number.isNaN(date.valueOf())) return date;
|
||||
}
|
||||
return new Date(0);
|
||||
}
|
||||
|
||||
function formatDate(date: Date): string {
|
||||
return new Intl.DateTimeFormat('zh-CN', {
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
}).format(date);
|
||||
}
|
||||
|
||||
function fallbackSlug(path: string): string {
|
||||
return path
|
||||
.split('/')
|
||||
.pop()
|
||||
?.replace(/\.md$/, '')
|
||||
.toLowerCase() ?? 'post';
|
||||
}
|
||||
|
||||
function makeSummary(module: MarkdownModule): string {
|
||||
const explicit = module.frontmatter.summary ?? module.frontmatter.description;
|
||||
if (typeof explicit === 'string' && explicit.trim()) return explicit.trim();
|
||||
|
||||
const raw = module.rawContent?.() ?? '';
|
||||
return raw
|
||||
.replace(/```[\s\S]*?```/g, '')
|
||||
.replace(/<[^>]+>/g, '')
|
||||
.replace(/[#>*_`~\-\[\]\(\)]/g, '')
|
||||
.replace(/\s+/g, ' ')
|
||||
.trim()
|
||||
.slice(0, 120);
|
||||
}
|
||||
|
||||
export function getAllPosts(): BlogPost[] {
|
||||
return Object.entries(modules)
|
||||
.map(([path, module]) => {
|
||||
const date = toDate(module.frontmatter.date);
|
||||
const slug = String(module.frontmatter.abbrlink ?? fallbackSlug(path));
|
||||
const title = String(module.frontmatter.title ?? slug);
|
||||
|
||||
return {
|
||||
...module,
|
||||
title,
|
||||
slug,
|
||||
date,
|
||||
dateText: formatDate(date),
|
||||
tags: asArray(module.frontmatter.tags),
|
||||
categories: asArray(module.frontmatter.categories),
|
||||
summary: makeSummary(module),
|
||||
href: `/posts/${slug}/`,
|
||||
};
|
||||
})
|
||||
.sort((a, b) => b.date.valueOf() - a.date.valueOf());
|
||||
}
|
||||
|
||||
export function getAllTags(): string[] {
|
||||
return [...new Set(getAllPosts().flatMap((post) => post.tags))].sort((a, b) => a.localeCompare(b, 'zh-CN'));
|
||||
}
|
||||
|
||||
export function getAllCategories(): string[] {
|
||||
return [...new Set(getAllPosts().flatMap((post) => post.categories))].sort((a, b) => a.localeCompare(b, 'zh-CN'));
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
---
|
||||
import BaseLayout from '@/layouts/BaseLayout.astro';
|
||||
import { getSitePages } from '@/lib/pages';
|
||||
|
||||
export function getStaticPaths() {
|
||||
return getSitePages().map((page) => ({
|
||||
params: { slug: page.slug },
|
||||
props: { page },
|
||||
}));
|
||||
}
|
||||
|
||||
const { page } = Astro.props;
|
||||
const { Content } = page;
|
||||
---
|
||||
|
||||
<BaseLayout title={page.title}>
|
||||
<article class="article">
|
||||
<header class="article-header">
|
||||
<h1>{page.title}</h1>
|
||||
</header>
|
||||
<div class="prose">
|
||||
<Content />
|
||||
</div>
|
||||
</article>
|
||||
</BaseLayout>
|
||||
@@ -0,0 +1,20 @@
|
||||
---
|
||||
import BaseLayout from '@/layouts/BaseLayout.astro';
|
||||
import { getAllPosts } from '@/lib/posts';
|
||||
|
||||
const posts = getAllPosts();
|
||||
---
|
||||
|
||||
<BaseLayout title="归档">
|
||||
<section class="content-wrap narrow">
|
||||
<h1>归档</h1>
|
||||
<div class="archive-list">
|
||||
{posts.map((post) => (
|
||||
<a href={post.href}>
|
||||
<time datetime={post.date.toISOString()}>{post.dateText}</time>
|
||||
<span>{post.title}</span>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
</BaseLayout>
|
||||
@@ -0,0 +1 @@
|
||||
export { GET } from './rss.xml.js';
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
import BaseLayout from '@/layouts/BaseLayout.astro';
|
||||
import PostCard from '@/components/PostCard.astro';
|
||||
import { getAllCategories, getAllPosts } from '@/lib/posts';
|
||||
|
||||
export function getStaticPaths() {
|
||||
return getAllCategories().map((category) => ({
|
||||
params: { category },
|
||||
props: { category },
|
||||
}));
|
||||
}
|
||||
|
||||
const { category } = Astro.props;
|
||||
const posts = getAllPosts().filter((post) => post.categories.includes(category));
|
||||
---
|
||||
|
||||
<BaseLayout title={category}>
|
||||
<section class="content-wrap">
|
||||
<h1>{category}</h1>
|
||||
<div class="post-list">
|
||||
{posts.map((post) => <PostCard post={post} />)}
|
||||
</div>
|
||||
</section>
|
||||
</BaseLayout>
|
||||
@@ -0,0 +1,21 @@
|
||||
---
|
||||
import BaseLayout from '@/layouts/BaseLayout.astro';
|
||||
import { getAllCategories, getAllPosts } from '@/lib/posts';
|
||||
|
||||
const posts = getAllPosts();
|
||||
const categories = getAllCategories();
|
||||
---
|
||||
|
||||
<BaseLayout title="分类">
|
||||
<section class="content-wrap narrow">
|
||||
<h1>分类</h1>
|
||||
<div class="term-grid">
|
||||
{categories.map((category) => (
|
||||
<a href={`/categories/${encodeURIComponent(category)}/`}>
|
||||
<span>{category}</span>
|
||||
<strong>{posts.filter((post) => post.categories.includes(category)).length}</strong>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
</BaseLayout>
|
||||
@@ -0,0 +1,26 @@
|
||||
---
|
||||
import BaseLayout from '@/layouts/BaseLayout.astro';
|
||||
import PostCard from '@/components/PostCard.astro';
|
||||
import { getAllPosts } from '@/lib/posts';
|
||||
|
||||
const posts = getAllPosts();
|
||||
---
|
||||
|
||||
<BaseLayout>
|
||||
<section class="hero">
|
||||
<div>
|
||||
<p class="eyebrow">写给日常、技术和正在发生的自己</p>
|
||||
<h1>Bi's Blog</h1>
|
||||
<p>把折腾、学习和生活片段安静地收在这里。</p>
|
||||
</div>
|
||||
</section>
|
||||
<section class="content-wrap">
|
||||
<div class="section-heading">
|
||||
<h2>最新文章</h2>
|
||||
<a href="/archives/">查看全部</a>
|
||||
</div>
|
||||
<div class="post-list">
|
||||
{posts.slice(0, 16).map((post) => <PostCard post={post} />)}
|
||||
</div>
|
||||
</section>
|
||||
</BaseLayout>
|
||||
@@ -0,0 +1,30 @@
|
||||
---
|
||||
import BaseLayout from '@/layouts/BaseLayout.astro';
|
||||
import { getAllPosts } from '@/lib/posts';
|
||||
|
||||
export function getStaticPaths() {
|
||||
return getAllPosts().map((post) => ({
|
||||
params: { slug: post.slug },
|
||||
props: { post },
|
||||
}));
|
||||
}
|
||||
|
||||
const { post } = Astro.props;
|
||||
const { Content } = post;
|
||||
---
|
||||
|
||||
<BaseLayout title={post.title} description={post.summary}>
|
||||
<article class="article">
|
||||
<header class="article-header">
|
||||
<time datetime={post.date.toISOString()}>{post.dateText}</time>
|
||||
<h1>{post.title}</h1>
|
||||
<div class="meta-list">
|
||||
{post.categories.map((category) => <a href={`/categories/${encodeURIComponent(category)}/`}>{category}</a>)}
|
||||
{post.tags.map((tag) => <a href={`/tags/${encodeURIComponent(tag)}/`}>#{tag}</a>)}
|
||||
</div>
|
||||
</header>
|
||||
<div class="prose">
|
||||
<Content />
|
||||
</div>
|
||||
</article>
|
||||
</BaseLayout>
|
||||
@@ -0,0 +1,18 @@
|
||||
import rss from '@astrojs/rss';
|
||||
import { getAllPosts } from '@/lib/posts';
|
||||
|
||||
export function GET(context) {
|
||||
const posts = getAllPosts();
|
||||
|
||||
return rss({
|
||||
title: "Bi's Blog",
|
||||
description: 'Personal blog by biss.',
|
||||
site: context.site,
|
||||
items: posts.map((post) => ({
|
||||
title: post.title,
|
||||
pubDate: post.date,
|
||||
description: post.summary,
|
||||
link: post.href,
|
||||
})),
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
import BaseLayout from '@/layouts/BaseLayout.astro';
|
||||
import PostCard from '@/components/PostCard.astro';
|
||||
import { getAllPosts, getAllTags } from '@/lib/posts';
|
||||
|
||||
export function getStaticPaths() {
|
||||
return getAllTags().map((tag) => ({
|
||||
params: { tag },
|
||||
props: { tag },
|
||||
}));
|
||||
}
|
||||
|
||||
const { tag } = Astro.props;
|
||||
const posts = getAllPosts().filter((post) => post.tags.includes(tag));
|
||||
---
|
||||
|
||||
<BaseLayout title={tag}>
|
||||
<section class="content-wrap">
|
||||
<h1>#{tag}</h1>
|
||||
<div class="post-list">
|
||||
{posts.map((post) => <PostCard post={post} />)}
|
||||
</div>
|
||||
</section>
|
||||
</BaseLayout>
|
||||
@@ -0,0 +1,21 @@
|
||||
---
|
||||
import BaseLayout from '@/layouts/BaseLayout.astro';
|
||||
import { getAllPosts, getAllTags } from '@/lib/posts';
|
||||
|
||||
const posts = getAllPosts();
|
||||
const tags = getAllTags();
|
||||
---
|
||||
|
||||
<BaseLayout title="标签">
|
||||
<section class="content-wrap narrow">
|
||||
<h1>标签</h1>
|
||||
<div class="term-grid">
|
||||
{tags.map((tag) => (
|
||||
<a href={`/tags/${encodeURIComponent(tag)}/`}>
|
||||
<span>{tag}</span>
|
||||
<strong>{posts.filter((post) => post.tags.includes(tag)).length}</strong>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
</BaseLayout>
|
||||
@@ -0,0 +1,295 @@
|
||||
:root {
|
||||
color-scheme: light;
|
||||
--bg: #f7f5ef;
|
||||
--surface: #fffdf8;
|
||||
--text: #20242a;
|
||||
--muted: #686f78;
|
||||
--line: #ded8cc;
|
||||
--accent: #0f766e;
|
||||
--accent-strong: #14532d;
|
||||
--shadow: 0 14px 45px rgba(58, 51, 38, 0.1);
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
color: var(--text);
|
||||
font-family:
|
||||
Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI",
|
||||
"Microsoft YaHei", sans-serif;
|
||||
line-height: 1.75;
|
||||
background:
|
||||
linear-gradient(rgba(247, 245, 239, 0.86), rgba(247, 245, 239, 0.95)),
|
||||
url('/images/background.png') center top / cover fixed;
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.site-header {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
border-bottom: 1px solid rgba(222, 216, 204, 0.8);
|
||||
background: rgba(255, 253, 248, 0.88);
|
||||
backdrop-filter: blur(14px);
|
||||
}
|
||||
|
||||
.nav {
|
||||
width: min(1120px, calc(100% - 32px));
|
||||
min-height: 64px;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.brand {
|
||||
font-size: 1.05rem;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 18px;
|
||||
color: var(--muted);
|
||||
font-size: 0.94rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.nav-links a:hover,
|
||||
.site-footer a:hover,
|
||||
.section-heading a:hover {
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.hero {
|
||||
width: min(1120px, calc(100% - 32px));
|
||||
min-height: 360px;
|
||||
margin: 0 auto;
|
||||
display: grid;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.hero h1 {
|
||||
margin: 0;
|
||||
font-size: clamp(3rem, 8vw, 6.5rem);
|
||||
line-height: 0.95;
|
||||
}
|
||||
|
||||
.hero p {
|
||||
max-width: 620px;
|
||||
margin: 18px 0 0;
|
||||
color: var(--muted);
|
||||
font-size: 1.12rem;
|
||||
}
|
||||
|
||||
.eyebrow {
|
||||
margin: 0 0 16px !important;
|
||||
color: var(--accent-strong) !important;
|
||||
font-size: 0.95rem !important;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.content-wrap {
|
||||
width: min(980px, calc(100% - 32px));
|
||||
margin: 0 auto 72px;
|
||||
}
|
||||
|
||||
.content-wrap.narrow {
|
||||
width: min(780px, calc(100% - 32px));
|
||||
}
|
||||
|
||||
.section-heading {
|
||||
display: flex;
|
||||
align-items: end;
|
||||
justify-content: space-between;
|
||||
gap: 20px;
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
|
||||
.section-heading h2,
|
||||
.content-wrap h1 {
|
||||
margin: 0;
|
||||
font-size: 1.8rem;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.section-heading a {
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.post-list {
|
||||
display: grid;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.post-card {
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 8px;
|
||||
padding: 22px;
|
||||
background: rgba(255, 253, 248, 0.88);
|
||||
box-shadow: var(--shadow);
|
||||
}
|
||||
|
||||
.post-card h2 {
|
||||
margin: 6px 0 8px;
|
||||
font-size: 1.35rem;
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
.post-card p {
|
||||
margin: 0;
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
time {
|
||||
color: var(--muted);
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.meta-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
margin-top: 14px;
|
||||
}
|
||||
|
||||
.meta-list a {
|
||||
border: 1px solid rgba(15, 118, 110, 0.28);
|
||||
border-radius: 999px;
|
||||
padding: 2px 10px;
|
||||
color: var(--accent);
|
||||
font-size: 0.86rem;
|
||||
background: rgba(236, 253, 245, 0.7);
|
||||
}
|
||||
|
||||
.article {
|
||||
width: min(820px, calc(100% - 32px));
|
||||
margin: 64px auto 84px;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 8px;
|
||||
padding: clamp(24px, 5vw, 48px);
|
||||
background: rgba(255, 253, 248, 0.93);
|
||||
box-shadow: var(--shadow);
|
||||
}
|
||||
|
||||
.article-header {
|
||||
margin-bottom: 28px;
|
||||
padding-bottom: 22px;
|
||||
border-bottom: 1px solid var(--line);
|
||||
}
|
||||
|
||||
.article-header h1 {
|
||||
margin: 8px 0 0;
|
||||
font-size: clamp(2rem, 6vw, 3.3rem);
|
||||
line-height: 1.14;
|
||||
}
|
||||
|
||||
.prose :where(h2, h3, h4) {
|
||||
margin-top: 2em;
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
.prose :where(p, ul, ol, blockquote, pre) {
|
||||
margin: 1.1em 0;
|
||||
}
|
||||
|
||||
.prose a {
|
||||
color: var(--accent);
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 3px;
|
||||
}
|
||||
|
||||
.prose img {
|
||||
max-width: 100%;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.prose pre {
|
||||
overflow-x: auto;
|
||||
border-radius: 8px;
|
||||
padding: 18px;
|
||||
}
|
||||
|
||||
.prose code {
|
||||
font-family: "JetBrains Mono", Consolas, monospace;
|
||||
}
|
||||
|
||||
.archive-list {
|
||||
margin-top: 24px;
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.archive-list a {
|
||||
display: grid;
|
||||
grid-template-columns: 116px 1fr;
|
||||
gap: 16px;
|
||||
border-bottom: 1px solid var(--line);
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
.term-grid {
|
||||
margin-top: 24px;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.term-grid a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 8px;
|
||||
padding: 14px 16px;
|
||||
background: rgba(255, 253, 248, 0.9);
|
||||
}
|
||||
|
||||
.site-footer {
|
||||
width: min(1120px, calc(100% - 32px));
|
||||
margin: 0 auto;
|
||||
padding: 32px 0 44px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 18px;
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
@media (max-width: 720px) {
|
||||
.nav {
|
||||
min-height: auto;
|
||||
padding: 14px 0;
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
gap: 14px;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
.hero {
|
||||
min-height: 300px;
|
||||
}
|
||||
|
||||
.archive-list a {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.article {
|
||||
margin-top: 32px;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user