feat: regularize front-matter, add new-post command

This commit is contained in:
saicaca 2023-10-18 17:31:11 +08:00
parent ad67a86ef9
commit 767d351bd5
15 changed files with 95 additions and 43 deletions

View File

@ -7,7 +7,8 @@
"start": "astro dev", "start": "astro dev",
"build": "astro build", "build": "astro build",
"preview": "astro preview", "preview": "astro preview",
"astro": "astro" "astro": "astro",
"new-post": "node scripts/new-post.js"
}, },
"dependencies": { "dependencies": {
"@astrojs/check": "^0.2.0", "@astrojs/check": "^0.2.0",

Binary file not shown.

After

Width:  |  Height:  |  Size: 877 KiB

52
scripts/new-post.js Normal file
View File

@ -0,0 +1,52 @@
import fs from 'fs';
import path from 'path';
function getDate() {
const today = new Date();
const year = today.getFullYear();
const month = String(today.getMonth() + 1).padStart(2, '0'); //月份从0开始所以要加1
const day = String(today.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
}
const args = process.argv.slice(2);
if (args.length === 0) {
console.error(`Error: No filename argument provided
Usage: npm run new-post -- <filename>`);
process.exit(1); // Terminate the script and return error code 1
}
let fileName = args[0];
// Add .md extension if not present
const fileExtensionRegex = /\.(md|mdx)$/i;
if (!fileExtensionRegex.test(fileName)) {
fileName += '.md';
}
const targetDir = './src/content/posts/';
const fullPath = path.join(targetDir, fileName);
if (fs.existsSync(fullPath)) {
console.error(`ErrorFile ${fullPath} already exists `);
process.exit(1);
}
const content =
`---
title: ${args[0]}
published: ${getDate()}
description:
cover:
url:
alt:
tags: []
categories: []
---
`;
fs.writeFileSync(path.join(targetDir, fileName), content);
console.log(`Post ${fullPath} created`);

View File

@ -26,7 +26,7 @@ if (Array.isArray(categories) && categories.length > 0) {
const groups = function () { const groups = function () {
const groupedPosts = posts.reduce((grouped, post) => { const groupedPosts = posts.reduce((grouped, post) => {
const year = post.data.pubDate.getFullYear() const year = post.data.published.getFullYear()
if (!grouped[year]) { if (!grouped[year]) {
grouped[year] = [] grouped[year] = []
} }
@ -73,7 +73,7 @@ function formatDate(date: Date) {
<Button light height="40px" class="w-full rounded-lg hover:text-[initial]"> <Button light height="40px" class="w-full rounded-lg hover:text-[initial]">
<div class="flex flex-row justify-start items-center h-full"> <div class="flex flex-row justify-start items-center h-full">
<!-- date --> <!-- date -->
<div class="w-[10%] transition text-sm text-right text-black/50 dark:text-white/50">{formatDate(post.data.pubDate)}</div> <div class="w-[10%] transition text-sm text-right text-black/50 dark:text-white/50">{formatDate(post.data.published)}</div>
<!-- dot and line --> <!-- dot and line -->
<div class="w-[10%] relative dash-line h-full flex items-center"> <div class="w-[10%] relative dash-line h-full flex items-center">
<div class="transition-all mx-auto w-1 h-1 rounded group-hover:h-5 <div class="transition-all mx-auto w-1 h-1 rounded group-hover:h-5

View File

@ -6,11 +6,11 @@ import I18nKey from "../i18n/i18nKey";
interface Props { interface Props {
class: string; class: string;
pubDate: Date; published: Date;
tags: string[]; tags: string[];
categories: string[]; categories: string[];
} }
const {pubDate, tags, categories} = Astro.props; const {published, tags, categories} = Astro.props;
const className = Astro.props.class; const className = Astro.props.class;
--- ---
@ -21,7 +21,7 @@ const className = Astro.props.class;
> >
<Icon name="material-symbols:calendar-today-outline-rounded" class="text-xl"></Icon> <Icon name="material-symbols:calendar-today-outline-rounded" class="text-xl"></Icon>
</div> </div>
<span class="text-black/50 dark:text-white/50 text-sm font-medium">{formatDateToYYYYMMDD(pubDate)}</span> <span class="text-black/50 dark:text-white/50 text-sm font-medium">{formatDateToYYYYMMDD(published)}</span>
</div> </div>
<!-- categories --> <!-- categories -->
@ -31,7 +31,7 @@ const className = Astro.props.class;
<Icon name="material-symbols:menu-rounded" class="text-xl"></Icon> <Icon name="material-symbols:menu-rounded" class="text-xl"></Icon>
</div> </div>
<div class="flex flex-row flex-nowrap"> <div class="flex flex-row flex-nowrap">
{categories && categories.map(category => <div {(categories && categories.length > 0) && categories.map(category => <div
class="with-divider" class="with-divider"
> >
<a href=`/archive/category/${category}` <a href=`/archive/category/${category}`
@ -40,7 +40,7 @@ const className = Astro.props.class;
{category} {category}
</a> </a>
</div>)} </div>)}
{!categories && <div class="transition text-black/50 dark:text-white/50 text-sm font-medium">{i18n(I18nKey.uncategorized)}</div>} {!(categories && categories.length > 0) && <div class="transition text-black/50 dark:text-white/50 text-sm font-medium">{i18n(I18nKey.uncategorized)}</div>}
</div> </div>
</div> </div>
@ -51,7 +51,7 @@ const className = Astro.props.class;
<Icon name="material-symbols:tag-rounded" class="text-xl"></Icon> <Icon name="material-symbols:tag-rounded" class="text-xl"></Icon>
</div> </div>
<div class="flex flex-row flex-nowrap"> <div class="flex flex-row flex-nowrap">
{tags && tags.map(tag => <div {(tags && tags.length > 0) && tags.map(tag => <div
class="with-divider" class="with-divider"
> >
<a href=`/archive/tag/${tag}` <a href=`/archive/tag/${tag}`
@ -60,7 +60,7 @@ const className = Astro.props.class;
{tag} {tag}
</a> </a>
</div>)} </div>)}
{!tags && <div class="transition text-black/50 dark:text-white/50 text-sm font-medium">{i18n(I18nKey.noTags)}</div>} {!(tags && tags.length > 0) && <div class="transition text-black/50 dark:text-white/50 text-sm font-medium">{i18n(I18nKey.noTags)}</div>}
</div> </div>
</div> </div>
</div> </div>

View File

@ -3,13 +3,13 @@ import {formatDateToYYYYMMDD} from "../utils/date-utils";
interface Props { interface Props {
title: string; title: string;
url: string; url: string;
pubDate: Date; published: Date;
tags: string[]; tags: string[];
cover: string; cover: string;
description: string; description: string;
words: number; words: number;
} }
const { title, url, pubDate, tags, cover, description, words } = Astro.props; const { title, url, published, tags, cover, description, words } = Astro.props;
// console.log(Astro.props); // console.log(Astro.props);
import ImageBox from "./misc/ImageBox.astro"; import ImageBox from "./misc/ImageBox.astro";
import ButtonTag from "./control/ButtonTag.astro"; import ButtonTag from "./control/ButtonTag.astro";
@ -40,7 +40,7 @@ const hasCover = cover !== undefined && cover !== null && cover !== '';
This is a very long title This is a very long title
</a> </a>
<div class="flex text-neutral-500 dark:text-neutral-400 items-center mb-1"> <div class="flex text-neutral-500 dark:text-neutral-400 items-center mb-1">
<div>{formatDateToYYYYMMDD(pubDate)}</div> <div>{formatDateToYYYYMMDD(published)}</div>
<div class="transition h-1 w-1 rounded-sm bg-neutral-400 dark:bg-neutral-600 mx-3"></div> <div class="transition h-1 w-1 rounded-sm bg-neutral-400 dark:bg-neutral-600 mx-3"></div>
<div>Uncategorized</div> <div>Uncategorized</div>
<div class="transition h-1 w-1 rounded-sm bg-neutral-400 dark:bg-neutral-600 mx-3"></div> <div class="transition h-1 w-1 rounded-sm bg-neutral-400 dark:bg-neutral-600 mx-3"></div>

View File

@ -5,14 +5,14 @@ interface Props {
entry: any; entry: any;
title: string; title: string;
url: string; url: string;
pubDate: Date; published: Date;
tags: string[]; tags: string[];
categories: string[]; categories: string[];
cover: string; cover: string;
description: string; description: string;
words: number; words: number;
} }
const { entry, title, url, pubDate, tags, categories, cover, description, words } = Astro.props; const { entry, title, url, published, tags, categories, cover, description, words } = Astro.props;
const className = Astro.props.class; const className = Astro.props.class;
// console.log(Astro.props); // console.log(Astro.props);
import ImageBox from "./misc/ImageBox.astro"; import ImageBox from "./misc/ImageBox.astro";
@ -46,7 +46,7 @@ const { remarkPluginFrontmatter } = await entry.render();
</a> </a>
<!-- metadata --> <!-- metadata -->
<PostMetadata pubDate={pubDate} tags={tags} categories={categories} class:list={{"mb-4": description, "mb-6": !description}}></PostMetadata> <PostMetadata published={published} tags={tags} categories={categories} class:list={{"mb-4": description, "mb-6": !description}}></PostMetadata>
<div class="transition text-black/75 dark:text-white/75 mb-4"> <div class="transition text-black/75 dark:text-white/75 mb-4">
{ description } { description }

View File

@ -1,11 +1,11 @@
--- ---
title: 'My First Blog Post' title: 'My First Blog Post'
pubDate: 2022-10-01 published: 2022-10-01
description: 'This is the first post of my new Astro blog.' description: 'This is the first post of my new Astro blog.'
author: 'Astro Learner' author: 'Astro Learner'
image: cover:
url: 'https://docs.astro.build/assets/full-logo-light.png' url:
alt: 'The full Astro logo.' alt:
tags: ["astro", "blogging", "learning in public"] tags: ["astro", "blogging", "learning in public"]
categories: ['Foo', 'Bar'] categories: ['Foo', 'Bar']
--- ---

View File

@ -1,13 +1,12 @@
--- ---
title: 'My Second Blog Post' title: 'My Second Blog Post'
pubDate: 2021-07-01 published: 2021-07-01
description: 'This is the first post of my new Astro blog.' description: 'This is the first post of my new Astro blog.'
author: 'Astro Learner' author: 'Astro Learner'
image: cover:
url: 'https://docs.astro.build/assets/full-logo-light.png' url: 'https://saicaca.github.io/vivia-preview/assets/79905307_p0.jpg'
alt: 'The full Astro logo.' alt:
tags: ["astro", "blogging", "learning in public"] tags: ["astro", "blogging", "learning in public"]
cover: 'https://saicaca.github.io/vivia-preview/assets/79905307_p0.jpg'
--- ---
# My First Blog Post # My First Blog Post

View File

@ -1,11 +1,11 @@
--- ---
title: 'My Third Blog Post' title: 'My Third Blog Post'
pubDate: 2020-07-01 published: 2020-07-01
description: 'This is the first post of my new Astro blog.' description: 'This is the first post of my new Astro blog.'
author: 'Astro Learner' author: 'Astro Learner'
image: cover:
url: 'https://docs.astro.build/assets/full-logo-light.png' url:
alt: 'The full Astro logo.' alt:
tags: ["astro", "blogging", "learning in public"] tags: ["astro", "blogging", "learning in public"]
--- ---
# My First Blog Post # My First Blog Post

View File

@ -1,11 +1,11 @@
--- ---
title: 'My Fourth Blog Post' title: 'My Fourth Blog Post'
pubDate: 2022-07-01 published: 2022-07-01
description: 'This is the first post of my new Astro blog.' description: 'This is the first post of my new Astro blog.'
author: 'Astro Learner' author: 'Astro Learner'
image: cover:
url: 'https://docs.astro.build/assets/full-logo-light.png' url:
alt: 'The full Astro logo.' alt:
tags: ["astro", "blogging", "learning in public"] tags: ["astro", "blogging", "learning in public"]
--- ---
# My First Blog Post # My First Blog Post

View File

@ -23,9 +23,9 @@ const {page} = Astro.props;
title={entry.data.title} title={entry.data.title}
tags={entry.data.tags} tags={entry.data.tags}
categories={entry.data.categories} categories={entry.data.categories}
pubDate={entry.data.pubDate} published={entry.data.published}
url={getPostUrlBySlug(entry.slug)} url={getPostUrlBySlug(entry.slug)}
cover={entry.data.cover} cover={entry.data.cover.url}
description={entry.data.description} description={entry.data.description}
></TitleCard> ></TitleCard>
)} )}

View File

@ -24,7 +24,7 @@ const { Content } = await entry.render();
const { remarkPluginFrontmatter } = await entry.render(); const { remarkPluginFrontmatter } = await entry.render();
--- ---
<MainGridLayout banner={entry.data.cover} title={entry.data.title}> <MainGridLayout banner={entry.data.cover.url} title={entry.data.title}>
<div class="flex w-full rounded-[var(--radius-large)] overflow-hidden relative mb-4"> <div class="flex w-full rounded-[var(--radius-large)] overflow-hidden relative mb-4">
<div class:list={["card-base z-10 px-4 md:px-9 py-6 relative w-full ", <div class:list={["card-base z-10 px-4 md:px-9 py-6 relative w-full ",
{} {}
@ -61,18 +61,18 @@ const { remarkPluginFrontmatter } = await entry.render();
<!-- metadata --> <!-- metadata -->
<PostMetadata <PostMetadata
class="mb-5" class="mb-5"
pubDate={entry.data.pubDate} published={entry.data.published}
tags={entry.data.tags} tags={entry.data.tags}
categories={entry.data.categories} categories={entry.data.categories}
></PostMetadata> ></PostMetadata>
<!-- always show cover as long as it has one --> <!-- always show cover as long as it has one -->
{entry.data.cover && {entry.data.cover.url &&
<ImageBox src={entry.data.cover} class="mb-8 rounded-xl"/> <ImageBox src={entry.data.cover.url} class="mb-8 rounded-xl"/>
} }
{!entry.data.cover && <div class="border-[var(--line-divider)] border-dashed border-b-[1px] mb-5"></div>} {!entry.data.cover.url && <div class="border-[var(--line-divider)] border-dashed border-b-[1px] mb-5"></div>}
<div class="prose dark:prose-invert prose-sm md:prose-base max-w-none custom-md <div class="prose dark:prose-invert prose-sm md:prose-base max-w-none custom-md
"> ">

View File

@ -3,8 +3,8 @@ import {CollectionEntry, getCollection} from "astro:content";
export async function getSortedPosts() { export async function getSortedPosts() {
const allBlogPosts = await getCollection("posts"); const allBlogPosts = await getCollection("posts");
const sorted = allBlogPosts.sort((a, b) => { const sorted = allBlogPosts.sort((a, b) => {
const dateA = new Date(a.data.pubDate); const dateA = new Date(a.data.published);
const dateB = new Date(b.data.pubDate); const dateB = new Date(b.data.published);
return dateA > dateB ? -1 : 1; return dateA > dateB ? -1 : 1;
}); });

View File

@ -11,7 +11,7 @@ lang: en
banner: banner:
enable: true enable: true
url: https://saicaca.github.io/vivia-preview/assets/banner.jpg url: /images/demo-banner.jpg
profile: profile:
avatar: https://saicaca.github.io/vivia-preview/assets/avatar.jpg avatar: https://saicaca.github.io/vivia-preview/assets/avatar.jpg