mirror of
				https://github.com/valentineus/popov.link.git
				synced 2025-11-04 06:49:45 +03:00 
			
		
		
		
	refactor: update blog post date handling and schema
- Replaced `pubDate` with `datePublished` in blog post components for consistency. - Updated sorting logic in blog sections to use `datePublished`. - Enhanced blog post schema to include `dateModified` for better structured data representation. - Adjusted various blog markdown files to reflect the new date fields.
This commit is contained in:
		@@ -8,7 +8,9 @@ type Props = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const { post } = Astro.props;
 | 
					const { post } = Astro.props;
 | 
				
			||||||
const { remarkPluginFrontmatter } = await post.render();
 | 
					const { remarkPluginFrontmatter } = await post.render();
 | 
				
			||||||
const formattedDate = dayjs(post.data.pubDate.toString()).format("MMMM DD, YYYY");
 | 
					
 | 
				
			||||||
 | 
					const formattedDate = dayjs(post.data.datePublished.toString()).format("MMMM DD, YYYY");
 | 
				
			||||||
 | 
					const datePublished = post.data.datePublished.toISOString();
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<style lang="scss">
 | 
					<style lang="scss">
 | 
				
			||||||
@@ -29,7 +31,7 @@ const formattedDate = dayjs(post.data.pubDate.toString()).format("MMMM DD, YYYY"
 | 
				
			|||||||
		<a href={`/blog/${post.slug}`} lang={post.data.lang}>{post.data.title}</a>
 | 
							<a href={`/blog/${post.slug}`} lang={post.data.lang}>{post.data.title}</a>
 | 
				
			||||||
		<div>
 | 
							<div>
 | 
				
			||||||
			<small>
 | 
								<small>
 | 
				
			||||||
				<time datetime={post.data.pubDate.toISOString()} lang="en">{formattedDate}</time>
 | 
									<time datetime={datePublished} lang="en">{formattedDate}</time>
 | 
				
			||||||
				<span>•</span>
 | 
									<span>•</span>
 | 
				
			||||||
				<span>{remarkPluginFrontmatter.minutesRead}</span>
 | 
									<span>{remarkPluginFrontmatter.minutesRead}</span>
 | 
				
			||||||
			</small>
 | 
								</small>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,7 +7,7 @@ const posts = await getCollection("blog", ({ data }) => {
 | 
				
			|||||||
	return data.draft !== true;
 | 
						return data.draft !== true;
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
posts.sort((a, b) => b.data.pubDate.getTime() - a.data.pubDate.getTime());
 | 
					posts.sort((a, b) => b.data.datePublished.getTime() - a.data.datePublished.getTime());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const latestPosts = posts.slice(0, 5);
 | 
					const latestPosts = posts.slice(0, 5);
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
@@ -32,8 +32,8 @@ const latestPosts = posts.slice(0, 5);
 | 
				
			|||||||
					</a>
 | 
										</a>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					<small>
 | 
										<small>
 | 
				
			||||||
						<time datetime={post.data.pubDate.toISOString()} lang="en">
 | 
											<time datetime={post.data.datePublished.toISOString()} lang="en">
 | 
				
			||||||
							{dayjs(post.data.pubDate.toString()).format("MMMM DD, YYYY")}
 | 
												{dayjs(post.data.datePublished.toString()).format("MMMM DD, YYYY")}
 | 
				
			||||||
						</time>
 | 
											</time>
 | 
				
			||||||
					</small>
 | 
										</small>
 | 
				
			||||||
				</li>
 | 
									</li>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +1,9 @@
 | 
				
			|||||||
---
 | 
					---
 | 
				
			||||||
title: 'Create ".lib" file from ".dll" (archive)'
 | 
					title: 'Create ".lib" file from ".dll" (archive)'
 | 
				
			||||||
author: "Adrian Henke"
 | 
					 | 
				
			||||||
pubDate: "2023-05-04"
 | 
					 | 
				
			||||||
description: "Learn how to generate a *.lib file from a *.dll with this comprehensive guide. Using the Visual Studio Command Prompt and Microsoft's recommended tools, this article walks you through the steps for a seamless process. Perfect for developers working with 3rd party win dll's."
 | 
					description: "Learn how to generate a *.lib file from a *.dll with this comprehensive guide. Using the Visual Studio Command Prompt and Microsoft's recommended tools, this article walks you through the steps for a seamless process. Perfect for developers working with 3rd party win dll's."
 | 
				
			||||||
 | 
					datePublished: "2023-05-04"
 | 
				
			||||||
 | 
					dateModified: "2023-05-04"
 | 
				
			||||||
 | 
					author: "Adrian Henke"
 | 
				
			||||||
lang: "en"
 | 
					lang: "en"
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +1,9 @@
 | 
				
			|||||||
---
 | 
					---
 | 
				
			||||||
title: "Горячая перезагрузка ElectronJS приложения"
 | 
					title: "Горячая перезагрузка ElectronJS приложения"
 | 
				
			||||||
author: "Valentin Popov"
 | 
					 | 
				
			||||||
pubDate: "2019-08-15"
 | 
					 | 
				
			||||||
description: "Руководство по автоматической перезагрузке приложений на Electron с помощью пакетов electron-reload и electron-webpack. Обход проблем с совместимостью и использование HMR для renderer процесса."
 | 
					description: "Руководство по автоматической перезагрузке приложений на Electron с помощью пакетов electron-reload и electron-webpack. Обход проблем с совместимостью и использование HMR для renderer процесса."
 | 
				
			||||||
 | 
					datePublished: "2019-08-15"
 | 
				
			||||||
 | 
					dateModified: "2019-08-15"
 | 
				
			||||||
 | 
					author: "Valentin Popov"
 | 
				
			||||||
lang: "ru"
 | 
					lang: "ru"
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +1,9 @@
 | 
				
			|||||||
---
 | 
					---
 | 
				
			||||||
title: "Example Content"
 | 
					title: "Example Content"
 | 
				
			||||||
author: "Example User"
 | 
					 | 
				
			||||||
pubDate: "2018-01-01"
 | 
					 | 
				
			||||||
description: "Howdy! This is an example blog post that shows several types of HTML content supported in this theme."
 | 
					description: "Howdy! This is an example blog post that shows several types of HTML content supported in this theme."
 | 
				
			||||||
 | 
					datePublished: "2018-01-01"
 | 
				
			||||||
 | 
					dateModified: "2018-01-01"
 | 
				
			||||||
 | 
					author: "Example User"
 | 
				
			||||||
lang: "en"
 | 
					lang: "en"
 | 
				
			||||||
draft: true
 | 
					draft: true
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +1,9 @@
 | 
				
			|||||||
---
 | 
					---
 | 
				
			||||||
title: 'Получение исходного кода "Chromium Projects"'
 | 
					title: 'Получение исходного кода "Chromium Projects"'
 | 
				
			||||||
author: "Valentin Popov"
 | 
					 | 
				
			||||||
pubDate: "2012-01-30"
 | 
					 | 
				
			||||||
description: "Изучение исходных кодов Chromium: подготовка системы и установка необходимых программных компонентов. Руководство для начинающих разработчиков. Получите инструкции по установке Microsoft Visual Studio, Cygwin, Python и других инструментов. Действительно на январь-февраль 2012 года."
 | 
					description: "Изучение исходных кодов Chromium: подготовка системы и установка необходимых программных компонентов. Руководство для начинающих разработчиков. Получите инструкции по установке Microsoft Visual Studio, Cygwin, Python и других инструментов. Действительно на январь-февраль 2012 года."
 | 
				
			||||||
 | 
					datePublished: "2012-01-30"
 | 
				
			||||||
 | 
					dateModified: "2012-01-30"
 | 
				
			||||||
 | 
					author: "Valentin Popov"
 | 
				
			||||||
lang: "ru"
 | 
					lang: "ru"
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +1,9 @@
 | 
				
			|||||||
---
 | 
					---
 | 
				
			||||||
title: "Установка Moodle в Fedora"
 | 
					title: "Установка Moodle в Fedora"
 | 
				
			||||||
author: "Valentin Popov"
 | 
					 | 
				
			||||||
pubDate: "2018-07-23"
 | 
					 | 
				
			||||||
description: "Решение проблем установки Moodle из-за SELinux: как настроить правила доступа для устранения ошибок в веб-интерфейсе и при работе с cURL. Практические советы и команды."
 | 
					description: "Решение проблем установки Moodle из-за SELinux: как настроить правила доступа для устранения ошибок в веб-интерфейсе и при работе с cURL. Практические советы и команды."
 | 
				
			||||||
 | 
					datePublished: "2018-07-23"
 | 
				
			||||||
 | 
					dateModified: "2018-07-23"
 | 
				
			||||||
 | 
					author: "Valentin Popov"
 | 
				
			||||||
lang: "ru"
 | 
					lang: "ru"
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +1,9 @@
 | 
				
			|||||||
---
 | 
					---
 | 
				
			||||||
title: "Компиляция Rust на TL-MR3020"
 | 
					title: "Компиляция Rust на TL-MR3020"
 | 
				
			||||||
author: "Valentin Popov"
 | 
					 | 
				
			||||||
pubDate: "2023-05-01"
 | 
					 | 
				
			||||||
description: 'Как настроить и оптимизировать проект Rust для кросс-компиляции на TP-Link TL-MR3020 с использованием Fedora Linux 38 и OpenWrt 22.03.4. Шаг за шагом от базового "Hello, World!" до асинхронного TCP сервера.'
 | 
					description: 'Как настроить и оптимизировать проект Rust для кросс-компиляции на TP-Link TL-MR3020 с использованием Fedora Linux 38 и OpenWrt 22.03.4. Шаг за шагом от базового "Hello, World!" до асинхронного TCP сервера.'
 | 
				
			||||||
 | 
					datePublished: "2023-05-01"
 | 
				
			||||||
 | 
					dateModified: "2023-05-01"
 | 
				
			||||||
 | 
					author: "Valentin Popov"
 | 
				
			||||||
lang: "ru"
 | 
					lang: "ru"
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,11 +4,12 @@ const blog = defineCollection({
 | 
				
			|||||||
	type: "content",
 | 
						type: "content",
 | 
				
			||||||
	schema: z.object({
 | 
						schema: z.object({
 | 
				
			||||||
		author: z.string(),
 | 
							author: z.string(),
 | 
				
			||||||
 | 
							dateModified: z.coerce.date(),
 | 
				
			||||||
 | 
							datePublished: z.coerce.date(),
 | 
				
			||||||
		description: z.string(),
 | 
							description: z.string(),
 | 
				
			||||||
		draft: z.optional(z.boolean()),
 | 
							draft: z.optional(z.boolean()),
 | 
				
			||||||
		pubDate: z.coerce.date(),
 | 
					 | 
				
			||||||
		title: z.string(),
 | 
					 | 
				
			||||||
		lang: z.string(),
 | 
							lang: z.string(),
 | 
				
			||||||
 | 
							title: z.string(),
 | 
				
			||||||
	}),
 | 
						}),
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,6 +9,7 @@ const lang = "en";
 | 
				
			|||||||
const schema = websiteSchema({
 | 
					const schema = websiteSchema({
 | 
				
			||||||
	siteUrl: new URL("/", Astro.site).toString(),
 | 
						siteUrl: new URL("/", Astro.site).toString(),
 | 
				
			||||||
	title,
 | 
						title,
 | 
				
			||||||
 | 
						description,
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,15 +27,18 @@ const description = post.data.description;
 | 
				
			|||||||
const author = post.data.author;
 | 
					const author = post.data.author;
 | 
				
			||||||
const lang = post.data.lang;
 | 
					const lang = post.data.lang;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const formattedData = dayjs(post.data.pubDate.toString()).format("MMMM DD, YYYY");
 | 
					const formattedDate = dayjs(post.data.datePublished.toString()).format("MMMM DD, YYYY");
 | 
				
			||||||
const data = post.data.pubDate.toISOString();
 | 
					const datePublished = post.data.datePublished.toISOString();
 | 
				
			||||||
 | 
					const dateModified = post.data.dateModified?.toISOString();
 | 
				
			||||||
 | 
					const slug = post.slug;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const schema = blogPostSchema({
 | 
					const schema = blogPostSchema({
 | 
				
			||||||
	siteUrl: new URL("/", Astro.site).toString(),
 | 
						siteUrl: new URL("/", Astro.site).toString(),
 | 
				
			||||||
	title,
 | 
						title,
 | 
				
			||||||
	description,
 | 
						description,
 | 
				
			||||||
	slug: post.slug,
 | 
						slug,
 | 
				
			||||||
	datePublished: data,
 | 
						datePublished,
 | 
				
			||||||
 | 
						dateModified,
 | 
				
			||||||
	author,
 | 
						author,
 | 
				
			||||||
	lang,
 | 
						lang,
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
@@ -57,7 +60,7 @@ const schema = blogPostSchema({
 | 
				
			|||||||
			<p>
 | 
								<p>
 | 
				
			||||||
				<small>
 | 
									<small>
 | 
				
			||||||
					Posted
 | 
										Posted
 | 
				
			||||||
					<time datetime={data} lang="en">{formattedData}</time>
 | 
										<time datetime={datePublished} lang="en">{formattedDate}</time>
 | 
				
			||||||
					by {author}
 | 
										by {author}
 | 
				
			||||||
					<span> • </span>
 | 
										<span> • </span>
 | 
				
			||||||
					<span>{remarkPluginFrontmatter.minutesRead}</span>
 | 
										<span>{remarkPluginFrontmatter.minutesRead}</span>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,10 +10,10 @@ const posts = await getCollection("blog", ({ data }) => {
 | 
				
			|||||||
	return data.draft !== true;
 | 
						return data.draft !== true;
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
posts.sort((a, b) => b.data.pubDate.getTime() - a.data.pubDate.getTime());
 | 
					posts.sort((a, b) => b.data.datePublished.getTime() - a.data.datePublished.getTime());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const postsByYear = posts.reduce<Record<string, CollectionEntry<"blog">[]>>((acc, post) => {
 | 
					const postsByYear = posts.reduce<Record<string, CollectionEntry<"blog">[]>>((acc, post) => {
 | 
				
			||||||
	const year = post.data.pubDate.getFullYear().toString();
 | 
						const year = post.data.datePublished.getFullYear().toString();
 | 
				
			||||||
	if (!acc[year]) {
 | 
						if (!acc[year]) {
 | 
				
			||||||
		acc[year] = [];
 | 
							acc[year] = [];
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,6 +12,7 @@ const lang = "en";
 | 
				
			|||||||
const schema = websiteSchema({
 | 
					const schema = websiteSchema({
 | 
				
			||||||
	siteUrl: new URL("/", Astro.site).toString(),
 | 
						siteUrl: new URL("/", Astro.site).toString(),
 | 
				
			||||||
	title,
 | 
						title,
 | 
				
			||||||
 | 
						description,
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,23 +1,24 @@
 | 
				
			|||||||
import type { WithContext, BlogPosting } from "schema-dts";
 | 
					import type { WithContext, BlogPosting } from "schema-dts";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type BlogPostSchemaParams = {
 | 
					export type BlogPostSchemaParams = {
 | 
				
			||||||
	readonly siteUrl: string;
 | 
					 | 
				
			||||||
	readonly title: string;
 | 
					 | 
				
			||||||
	readonly description: string;
 | 
					 | 
				
			||||||
	readonly slug: string;
 | 
					 | 
				
			||||||
	readonly datePublished: string;
 | 
					 | 
				
			||||||
	readonly author: string;
 | 
						readonly author: string;
 | 
				
			||||||
 | 
						readonly dateModified: string;
 | 
				
			||||||
 | 
						readonly datePublished: string;
 | 
				
			||||||
 | 
						readonly description: string;
 | 
				
			||||||
	readonly lang: string;
 | 
						readonly lang: string;
 | 
				
			||||||
 | 
						readonly siteUrl: string;
 | 
				
			||||||
 | 
						readonly slug: string;
 | 
				
			||||||
 | 
						readonly title: string;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default ({ siteUrl, title, description, slug, datePublished, author, lang }: BlogPostSchemaParams): WithContext<BlogPosting> => ({
 | 
					export default ({ siteUrl, slug, title, description, datePublished, dateModified, author, lang }: BlogPostSchemaParams): WithContext<BlogPosting> => ({
 | 
				
			||||||
	"@context": "https://schema.org",
 | 
						"@context": "https://schema.org",
 | 
				
			||||||
	"@type": "BlogPosting",
 | 
						"@type": "BlogPosting",
 | 
				
			||||||
	"url": new URL(`/blog/${slug}`, siteUrl).toString(),
 | 
						"url": new URL(`/blog/${slug}`, siteUrl).toString(),
 | 
				
			||||||
	"headline": title,
 | 
						"headline": title,
 | 
				
			||||||
	"description": description,
 | 
						"description": description,
 | 
				
			||||||
	"datePublished": datePublished,
 | 
						"datePublished": datePublished,
 | 
				
			||||||
	"dateModified": datePublished,
 | 
						"dateModified": dateModified,
 | 
				
			||||||
	"inLanguage": lang,
 | 
						"inLanguage": lang,
 | 
				
			||||||
	"author": {
 | 
						"author": {
 | 
				
			||||||
		"@type": "Person",
 | 
							"@type": "Person",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,9 +2,9 @@ import type { WithContext, CollectionPage } from "schema-dts";
 | 
				
			|||||||
import type { CollectionEntry } from "astro:content";
 | 
					import type { CollectionEntry } from "astro:content";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type BlogSchemaParams = {
 | 
					export type BlogSchemaParams = {
 | 
				
			||||||
 | 
						readonly posts: CollectionEntry<"blog">[];
 | 
				
			||||||
	readonly siteUrl: string;
 | 
						readonly siteUrl: string;
 | 
				
			||||||
	readonly title: string;
 | 
						readonly title: string;
 | 
				
			||||||
	readonly posts: CollectionEntry<"blog">[];
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default ({ siteUrl, title, posts }: BlogSchemaParams): WithContext<CollectionPage> => ({
 | 
					export default ({ siteUrl, title, posts }: BlogSchemaParams): WithContext<CollectionPage> => ({
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,13 +1,15 @@
 | 
				
			|||||||
import type { WithContext, WebSite } from "schema-dts";
 | 
					import type { WithContext, WebSite } from "schema-dts";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type WebsiteSchemaParams = {
 | 
					export type WebsiteSchemaParams = {
 | 
				
			||||||
 | 
						readonly description: string;
 | 
				
			||||||
	readonly siteUrl: string;
 | 
						readonly siteUrl: string;
 | 
				
			||||||
	readonly title: string;
 | 
						readonly title: string;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default ({ siteUrl, title }: WebsiteSchemaParams): WithContext<WebSite> => ({
 | 
					export default ({ siteUrl, title, description }: WebsiteSchemaParams): WithContext<WebSite> => ({
 | 
				
			||||||
	"@context": "https://schema.org",
 | 
						"@context": "https://schema.org",
 | 
				
			||||||
	"@type": "WebSite",
 | 
						"@type": "WebSite",
 | 
				
			||||||
	"url": new URL("/", siteUrl).toString(),
 | 
						"url": new URL("/", siteUrl).toString(),
 | 
				
			||||||
	"name": title,
 | 
						"name": title,
 | 
				
			||||||
 | 
						"description": description,
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user