recent articles render

This commit is contained in:
Sergey Yarkov 2023-02-18 18:53:19 +03:00
parent c311050b65
commit a334a67b03
No known key found for this signature in database
GPG Key ID: E91CE1FABC619B6F
10 changed files with 76 additions and 41 deletions

View File

@ -5,14 +5,15 @@ import { createDateFormatter } from "@root/utils";
import ArticleCover from "@components/ArticleCover.astro"; import ArticleCover from "@components/ArticleCover.astro";
import ArticleComments from "@components/ArticleComments.astro"; import ArticleComments from "@components/ArticleComments.astro";
// import TranslatedLink from "../TranslatedLink"; // import TranslatedLink from "../TranslatedLink";
// import { useTranslation } from "@i18n/utils"; import { useTranslation, getLanguageFromURL } from "@i18n/utils";
export type Props = { export type Props = {
article: CollectionEntry<"blog">; article: CollectionEntry<"blog">;
lang: string; lang: string;
}; };
const { article, lang } = Astro.props as Props; const { article } = Astro.props as Props;
const pageLang = getLanguageFromURL(Astro.url.pathname);
const canonicalUrl = new URL(Astro.url.pathname, Astro.site); const canonicalUrl = new URL(Astro.url.pathname, Astro.site);
const { const {
data: { coverImage, title, author, description, tags, pubDate }, data: { coverImage, title, author, description, tags, pubDate },
@ -50,7 +51,7 @@ const {
</div> </div>
<div class="published"> <div class="published">
<time itemprop="datePublished" datetime={pubDate.toString()}> <time itemprop="datePublished" datetime={pubDate.toString()}>
{createDateFormatter(lang).format(pubDate)} {createDateFormatter(pageLang).format(pubDate)}
</time> </time>
<span itemprop="author">{author}</span> <span itemprop="author">{author}</span>
</div> </div>

View File

@ -3,19 +3,20 @@ import { SITE_METADATA } from "@root/constants";
import { Icon } from "astro-icon"; import { Icon } from "astro-icon";
import TranslatedLink from "./TranslatedLink.astro"; import TranslatedLink from "./TranslatedLink.astro";
import UIString from "./UIString.astro"; import UIString from "./UIString.astro";
const date = new Date();
--- ---
<footer> <footer>
<div class="container"> <div class="container">
<div> <div>
<i> <i>
Разработка: <TranslatedLink to="/contacts">{SITE_METADATA.author}</TranslatedLink> <UIString key={"footer.developed"} />: <TranslatedLink to="/contacts">
&copy; {date.getFullYear()} {SITE_METADATA.author}
</TranslatedLink>
&copy; {new Date().getFullYear()}
</i> </i>
</div> </div>
<div> <div>
<a href="/rss.xml" target="_blank"><UIString key={"rss.feed"} /></a> <a href="/rss.xml" target="_blank"><UIString key={"footer.rssFeed"} /></a>
<span> <span>
<Icon name="rss" width="20" height="20" /> <Icon name="rss" width="20" height="20" />
</span> </span>
@ -27,14 +28,18 @@ const date = new Date();
footer { footer {
font-weight: 500; font-weight: 500;
margin-top: 5rem; margin-top: 5rem;
color: var(--color-gray-200); color: var(--color-gray-400);
font-size: var(--font-size-sm); font-size: var(--font-size-sm);
& .container { & .container {
padding: 15px 0 15px 0; padding-top: 15px;
padding-bottom: 15px;
border-top: 1px solid var(--border-color); border-top: 1px solid var(--border-color);
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
flex-wrap: wrap;
column-gap: 20px;
row-gap: 5px;
& div:last-child { & div:last-child {
display: flex; display: flex;
align-items: center; align-items: center;

View File

@ -1,35 +1,35 @@
--- ---
import type { CollectionEntry } from "astro:content"; import type { CollectionEntry } from "astro:content";
import siteconfig from "siteconfig.json"; import siteconfig from "siteconfig.json";
import { getLanguageFromURL } from "@i18n/utils";
import * as utils from "@utils/index";
import ArticleItem from "@components/ArticleItem.astro"; import ArticleItem from "@components/ArticleItem.astro";
import EmptyList from "@components/EmptyList.astro"; import EmptyList from "@components/EmptyList.astro";
import UIString from "@components/UIString.astro"; import UIString from "@components/UIString.astro";
import TranslatedLink from "@components/TranslatedLink.astro"; import TranslatedLink from "@components/TranslatedLink.astro";
export interface Props { export interface Props {
articles: CollectionEntry<"blog">[]; articles: CollectionEntry<"blog">[];
length?: number | undefined; length?: number | undefined;
} }
const { articles, length = siteconfig.articles.recentLimit } = Astro.props as Props; const { articles, length = siteconfig.articles.recentLimit } = Astro.props as Props;
const pageLang = getLanguageFromURL(Astro.url.pathname);
const filtered = utils.removeDuplicates(articles.slice(0, length), pageLang);
const isEmpty = articles.length === 0; const isEmpty = articles.length === 0;
--- ---
<section> <section>
<div> <div>
<h2><UIString key={"recentArticles.heading"} /></h2> <h2>
<UIString key={"recentArticles.heading"} />
</h2>
<TranslatedLink to="/articles"> <TranslatedLink to="/articles">
<UIString key={"recentArticles.all"} /> <UIString key={"recentArticles.all"} />
</TranslatedLink> </TranslatedLink>
</div> </div>
<div itemscope itemtype="http://schema.org/Blog"> <div itemscope itemtype="http://schema.org/Blog">
{ {!isEmpty ? filtered.map((article) => <ArticleItem entry={article} />) : <EmptyList />}
!isEmpty ? (
articles.slice(0, length).map((article) => <ArticleItem entry={article} />)
) : (
<EmptyList />
)
}
</div> </div>
</section> </section>

View File

@ -1,16 +0,0 @@
---
coverImage: null
draft: false
author: Sergey Yarkov
title: 74HC595 shift register control by microcontroller
description: This tutorial shows how to control the shift register of the
74HC595 in conjunction with the AVR microcontroller.
tags:
- AVR
- Digital Electronics
- Tutorial
pubDate: 2023-02-14T19:23:55.622Z
updatedDate: 2023-02-14T19:23:55.646Z
---
...

View File

@ -53,6 +53,7 @@ export default {
"form.contactError": "An error occurred while sending. Please try again later.", "form.contactError": "An error occurred while sending. Please try again later.",
/* Error messages */ /* Error messages */
"error.invalidEmail": "Fill in the field in the e-mail format.", "error.invalidEmail": "Fill in the field in the e-mail format.",
/* Other */ /* Footer */
"rss.feed": "RSS Feed", "footer.rssFeed": "RSS Feed",
"footer.developed": "Developed",
}; };

View File

@ -54,6 +54,7 @@ export default {
"form.contactError": "При отправке произошла ошибка. Повторите запрос позже.", "form.contactError": "При отправке произошла ошибка. Повторите запрос позже.",
/* Error messages */ /* Error messages */
"error.invalidEmail": "Заполните поле в формате e-mail.", "error.invalidEmail": "Заполните поле в формате e-mail.",
/* Other */ /* Footer */
"rss.feed": "RSS Лента", "footer.rssFeed": "RSS Лента",
"footer.developed": "Разработка",
}; };

33
src/utils/article.ts Normal file
View File

@ -0,0 +1,33 @@
import type { CollectionEntry } from "astro:content";
import { findDuplicates } from "./string";
import { removeLanguageCodeFromPath } from "./url";
/**
* If there is a translation of an article in the current language of the page,
* the remaining articles with other translations should be removed.
*
* @param entries Array of articles
* @param pageLang Current language on page
* @returns
*/
export function removeDuplicates(
entries: CollectionEntry<"blog">[],
pageLang: LanguageKeys
): CollectionEntry<"blog">[] {
const ids = entries.map((a) => a.id) as string[];
const duplicates = findDuplicates(ids.map((id) => removeLanguageCodeFromPath(id)));
duplicates.forEach((id) => {
const toDeleteIdxs: number[] = [];
if (ids.indexOf(`${pageLang}/${id}`) !== -1) {
entries.forEach((a, i) => {
if (a.id !== `${pageLang}/${id}` && a.id.includes(id)) {
toDeleteIdxs.push(i);
}
});
}
toDeleteIdxs.forEach((i) => entries.splice(i, 1));
});
return entries;
}

View File

@ -1,3 +1,5 @@
export * from "./date"; export * from "./date";
export * from "./history"; export * from "./history";
export * from "./url"; export * from "./url";
export * from "./string";
export * from "./article";

View File

@ -7,7 +7,11 @@ export function isEmail(email: string): boolean {
} }
export function isURL(url: string): boolean { export function isURL(url: string): boolean {
return new RegExp(/(http|ftp|https):\/\/([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:\\/~+#-]*[\w@?^=%&\\/~+#-])/).test( return new RegExp(
url /(http|ftp|https):\/\/([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:\\/~+#-]*[\w@?^=%&\\/~+#-])/
); ).test(url);
}
export function findDuplicates(array: string[]): string[] {
return array.filter((item, i) => array.indexOf(item) !== i);
} }

View File

@ -3,3 +3,7 @@ export const encode = (data: object) => {
.map((key) => encodeURIComponent(key) + "=" + encodeURIComponent(data[key])) .map((key) => encodeURIComponent(key) + "=" + encodeURIComponent(data[key]))
.join("&"); .join("&");
}; };
export function removeLanguageCodeFromPath(path: string) {
return path.replace(/^[a-zA-Z-]+\/+/, "");
}