mirror of
https://github.com/sergeyyarkov/yarkov.tech.git
synced 2026-10-11 02:19:08 +03:00
refactor
This commit is contained in:
parent
60c6bb5505
commit
43950ae134
@ -206,6 +206,9 @@
|
||||
& .languages-available {
|
||||
margin: 25px 0;
|
||||
font-size: var(--font-size-lg);
|
||||
& a:not(:last-child)::after {
|
||||
content: ",";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,23 +1,19 @@
|
||||
---
|
||||
import type { CollectionEntry } from "astro:content";
|
||||
import slugify from "@sindresorhus/slugify";
|
||||
import { URL_BLOG_PREFIX } from "@root/pages/[...blog].astro";
|
||||
import { DEFAULT_LANGUAGE } from "@root/constants";
|
||||
import { getLanguageFromURL } from "@i18n/utils";
|
||||
import { createDateFormatter } from "@root/utils";
|
||||
import { createDateFormatter, createRelativeArticleUrl } from "@root/utils";
|
||||
|
||||
export interface Props {
|
||||
entry: CollectionEntry<"blog">;
|
||||
}
|
||||
|
||||
const pageLang = getLanguageFromURL(Astro.url.pathname);
|
||||
const { entry } = Astro.props as Props;
|
||||
const {
|
||||
entry: {
|
||||
id,
|
||||
data: { title, pubDate },
|
||||
},
|
||||
} = Astro.props as Props;
|
||||
const slug = slugify(title, { lowercase: true });
|
||||
id,
|
||||
data: { title, pubDate },
|
||||
} = entry;
|
||||
const articleLang = id.split("/")[0];
|
||||
---
|
||||
|
||||
@ -27,11 +23,7 @@ const articleLang = id.split("/")[0];
|
||||
itemtype="http://schema.org/BlogPosting"
|
||||
class="article-item"
|
||||
>
|
||||
<a
|
||||
href={articleLang === DEFAULT_LANGUAGE
|
||||
? `/${URL_BLOG_PREFIX}/${pubDate.toISOString().split("T")[0]}/${slug}`
|
||||
: `/${articleLang}/${URL_BLOG_PREFIX}/${pubDate.toISOString().split("T")[0]}/${slug}`}
|
||||
>
|
||||
<a href={`${createRelativeArticleUrl(entry, URL_BLOG_PREFIX)}`}>
|
||||
<div class="flex">
|
||||
<h3 itemprop="headline">{title}</h3>
|
||||
{articleLang !== pageLang && <sup>{articleLang.toLocaleUpperCase()}</sup>}
|
||||
|
||||
@ -16,14 +16,13 @@ const { heading, description } = Astro.props as Props;
|
||||
<style lang="scss">
|
||||
div {
|
||||
margin-bottom: 2.5rem;
|
||||
text-align: center;
|
||||
& h1 {
|
||||
font-size: var(--font-size-4xl);
|
||||
text-align: center;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
& p {
|
||||
font-size: var(--font-size-lg);
|
||||
text-align: center;
|
||||
max-width: 650px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@ import { defineCollection, z } from "astro:content";
|
||||
const blog = defineCollection({
|
||||
schema: z.object({
|
||||
title: z.string(),
|
||||
draft: z.boolean().optional(),
|
||||
draft: z.boolean().nullable().optional(),
|
||||
coverImage: z.string().nullable().optional(),
|
||||
author: z.string(),
|
||||
tags: z.string().array().optional(),
|
||||
|
||||
@ -27,7 +27,7 @@ function transformExports<T>(modules: Record<string, { default: T }>) {
|
||||
const translations: Record<string, T> = {};
|
||||
for (const [path, module] of Object.entries(modules)) {
|
||||
const [, lang] = path.split("/");
|
||||
translations[lang as LanguageKeys] = module.default;
|
||||
translations[lang] = module.default;
|
||||
}
|
||||
return translations;
|
||||
}
|
||||
@ -36,7 +36,7 @@ const translations = transformExports<Record<string, UIDictionaryKeys>>(
|
||||
import.meta.glob("./*/ui.ts", { eager: true })
|
||||
);
|
||||
|
||||
function translate(key: UIDictionaryKeys, lang: LanguageKeys): string {
|
||||
export function translate(key: UIDictionaryKeys, lang: LanguageKeys): string {
|
||||
const value = translations[lang]?.[key] || translations[DEFAULT_LANGUAGE][key];
|
||||
if (value === undefined) console.log(`Cannot find any string for translation key "${key}".`);
|
||||
return value;
|
||||
|
||||
@ -1,8 +1,12 @@
|
||||
---
|
||||
import { CollectionEntry, getCollection } from "astro:content";
|
||||
import ArticleLayout from "@root/layouts/article.astro";
|
||||
import { DEFAULT_LANGUAGE } from "@root/constants";
|
||||
import slugify from "@sindresorhus/slugify";
|
||||
import { createRelativeArticleUrl, removeLanguageCodeFromPath } from "@root/utils";
|
||||
import { getLanguageFromURL, useTranslation } from "@i18n/utils";
|
||||
import languages from "@i18n/languages";
|
||||
|
||||
const t = useTranslation(Astro);
|
||||
const pageLang = getLanguageFromURL(Astro.url.pathname);
|
||||
|
||||
export const URL_BLOG_PREFIX = "blog";
|
||||
|
||||
@ -14,23 +18,39 @@ export const URL_BLOG_PREFIX = "blog";
|
||||
export async function getStaticPaths() {
|
||||
const collection = await getCollection("blog", (e) => !e.data.draft);
|
||||
return collection.map((article) => {
|
||||
const [languageCode] = article.slug.split("/");
|
||||
const slug = slugify(article.data.title, { lowercase: true });
|
||||
const pubDate = article.data.pubDate.toISOString().split("T")[0];
|
||||
const url =
|
||||
DEFAULT_LANGUAGE !== languageCode
|
||||
? `${languageCode}/${URL_BLOG_PREFIX}/${pubDate}/${slug}`
|
||||
: `${URL_BLOG_PREFIX}/${pubDate}/${slug}`;
|
||||
|
||||
return { params: { blog: url }, props: { article } };
|
||||
const url = createRelativeArticleUrl(article);
|
||||
return {
|
||||
params: { blog: url.slice(1) },
|
||||
props: {
|
||||
article,
|
||||
availableOnLang: collection.filter((e) =>
|
||||
e.id.includes(removeLanguageCodeFromPath(article.id))
|
||||
),
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
type Props = { article: CollectionEntry<"blog"> };
|
||||
type Props = { article: CollectionEntry<"blog">; availableOnLang: CollectionEntry<"blog">[] };
|
||||
|
||||
const { Content } = await Astro.props.article.render();
|
||||
const { article, availableOnLang } = Astro.props;
|
||||
---
|
||||
|
||||
<ArticleLayout article={Astro.props.article}>
|
||||
<ArticleLayout lang={article.id.split("/")[0]} article={article}>
|
||||
{
|
||||
availableOnLang.length > 1 && (
|
||||
<div class="languages-available">
|
||||
{t("article.availableOn")}:{" "}
|
||||
{availableOnLang
|
||||
.filter((a) => !a.id.startsWith(`${pageLang}/`))
|
||||
.map((a) => (
|
||||
<a href={`${createRelativeArticleUrl(a, URL_BLOG_PREFIX)}`}>{`${
|
||||
languages[a.id.split("/")[0] as LanguageKeys]
|
||||
}`}</a>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
<Content />
|
||||
</ArticleLayout>
|
||||
|
||||
@ -2,15 +2,18 @@ import rss from "@astrojs/rss";
|
||||
import { getCollection } from "astro:content";
|
||||
import { SITE_METADATA } from "@root/constants";
|
||||
import type { APIContext } from "astro";
|
||||
import * as utils from "@i18n/utils";
|
||||
|
||||
// TODO: generate feed for RU, EN, ... languages
|
||||
export async function get(context: APIContext) {
|
||||
const posts = await getCollection("blog");
|
||||
const posts = await getCollection("blog", (e) => !e.data.draft);
|
||||
return rss({
|
||||
title: SITE_METADATA.title,
|
||||
description: "",
|
||||
site: context.site,
|
||||
description: utils.translate("site.description", "ru"),
|
||||
site: "https://yarkov.tech",
|
||||
items: posts.map((post) => ({
|
||||
...post.data,
|
||||
title: post.data.title,
|
||||
pubDate: post.data.pubDate,
|
||||
link: `/blog/${post.slug}/`,
|
||||
})),
|
||||
});
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
import type { CollectionEntry } from "astro:content";
|
||||
import { DEFAULT_LANGUAGE } from "@root/constants";
|
||||
import slugify from "@sindresorhus/slugify";
|
||||
import { findDuplicates } from "./string";
|
||||
import { removeLanguageCodeFromPath } from "./url";
|
||||
|
||||
@ -31,3 +33,15 @@ export function removeDuplicates(
|
||||
|
||||
return entries;
|
||||
}
|
||||
|
||||
export function createRelativeArticleUrl(
|
||||
article: CollectionEntry<"blog">,
|
||||
prefix: string = "blog"
|
||||
): string {
|
||||
const articleLang = article.id.split("/")[0];
|
||||
const date = article.data.pubDate.toISOString().split("T")[0];
|
||||
return `${articleLang !== DEFAULT_LANGUAGE ? "/" + articleLang : ""}/${prefix}/${date}/${slugify(
|
||||
article.data.title,
|
||||
{ lowercase: true }
|
||||
)}`;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user