From 464b6c5c9cea0ed6642a71185465f96421b3d839 Mon Sep 17 00:00:00 2001 From: sergeyyarkov Date: Sun, 16 Apr 2023 22:26:01 +0300 Subject: [PATCH] feat: added table of contents --- src/components/ArticleContent.astro | 32 ++++++---------- src/components/ArticlePost.astro | 21 +++++++++-- src/components/AvailableOnLangs.astro | 42 +++++++++++++++++++++ src/components/TableOfContents.astro | 54 +++++++++++++++++++++++---- src/i18n/en/ui.ts | 1 + src/i18n/ru/ui.ts | 1 + src/layouts/article.astro | 9 +++-- src/pages/[...blog].astro | 32 +++++----------- src/utils/article.ts | 4 +- 9 files changed, 137 insertions(+), 59 deletions(-) create mode 100644 src/components/AvailableOnLangs.astro diff --git a/src/components/ArticleContent.astro b/src/components/ArticleContent.astro index ba29de4..cf3ef10 100644 --- a/src/components/ArticleContent.astro +++ b/src/components/ArticleContent.astro @@ -2,6 +2,7 @@ diff --git a/src/components/TableOfContents.astro b/src/components/TableOfContents.astro index fd01af9..ad4bb10 100644 --- a/src/components/TableOfContents.astro +++ b/src/components/TableOfContents.astro @@ -2,22 +2,62 @@ import { buildToc } from "@root/utils"; import type { MarkdownHeading } from "astro"; import TableOfContentsHeading from "./TableOfContentsHeading.astro"; +import { useTranslation } from "@root/i18n/utils"; export interface Props { headings: MarkdownHeading[]; } -const toc = buildToc(Astro.props.headings); +const toc = buildToc(Astro.props.headings, 3); +const t = useTranslation(Astro); --- - +
+ {t("article.tableOfContents")} + +
+ + diff --git a/src/i18n/en/ui.ts b/src/i18n/en/ui.ts index 0a7a174..2739b69 100644 --- a/src/i18n/en/ui.ts +++ b/src/i18n/en/ui.ts @@ -4,6 +4,7 @@ export default { "Here I publish articles and tutorials on various IT topics, and I also talk about my projects that I have done over the past few years.", "site.underConstruction": "This web-site is under development...", "article.availableOn": "Available on", + "article.tableOfContents": "Table of contents", "articles.empty": "No articles found...", "articlePost.comments": "Comments", "article.views": "views", diff --git a/src/i18n/ru/ui.ts b/src/i18n/ru/ui.ts index 77f4fa2..78a13bc 100644 --- a/src/i18n/ru/ui.ts +++ b/src/i18n/ru/ui.ts @@ -4,6 +4,7 @@ export default { "Здесь я публикую статьи и туториалы на разные IT темы, а также рассказываю о своих проектах которые я сделал за последние несколько лет.", "site.underConstruction": "Этот веб-сайт находится в разработке...", "article.availableOn": "Доступно на", + "article.tableOfContents": "Оглавление", "articles.empty": "Не найдено ни одной статьи...", "articlePost.comments": "Комментарии", "article.views": "просмотров", diff --git a/src/layouts/article.astro b/src/layouts/article.astro index 1f9a605..ce55910 100644 --- a/src/layouts/article.astro +++ b/src/layouts/article.astro @@ -8,15 +8,18 @@ import ArticleContent from "@components/ArticleContent.astro"; import ArticlePost from "@components/ArticlePost.astro"; import OpenGraph from "@components/OpenGraph.astro"; import TableOfContents from "@root/components/TableOfContents.astro"; +import { useTranslation } from "@root/i18n/utils"; export interface Props { lang?: string | undefined; article: CollectionEntry<"blog">; + availableOnLangs?: CollectionEntry<"blog">[]; headings: MarkdownHeading[]; } const canonicalUrl = new URL(Astro.url.pathname, Astro.site); -const { lang = DEFAULT_LANGUAGE, article, headings } = Astro.props as Props; +const t = useTranslation(Astro); +const { lang = DEFAULT_LANGUAGE, article, headings, availableOnLangs } = Astro.props as Props; const { data: { title, description, coverImage }, } = article; @@ -39,8 +42,8 @@ const {
- - + + diff --git a/src/pages/[...blog].astro b/src/pages/[...blog].astro index 79c8d0a..79f2f6d 100644 --- a/src/pages/[...blog].astro +++ b/src/pages/[...blog].astro @@ -3,11 +3,6 @@ import { CollectionEntry, getCollection } from "astro:content"; import ArticleLayout from "@root/layouts/article.astro"; import { createRelativeArticleUrl, removeLanguageCodeFromPath } from "@root/utils"; import { getLanguageFromURL, useTranslation } from "@i18n/utils"; -import { URL_BLOG_PREFIX } from "@root/constants"; -import languages from "@i18n/languages"; - -const t = useTranslation(Astro); -const pageLang = getLanguageFromURL(Astro.url.pathname); /** * Generate articles pages from `blog` collection. @@ -26,7 +21,7 @@ export async function getStaticPaths() { params: { blog: url.slice(1) }, props: { article, - availableOnLang: collection.filter((e) => + availableOnLangs: collection.filter((e) => e.id.includes(removeLanguageCodeFromPath(article.id)) ), }, @@ -34,26 +29,17 @@ export async function getStaticPaths() { }); } -type Props = { article: CollectionEntry<"blog">; availableOnLang: CollectionEntry<"blog">[] }; +type Props = { article: CollectionEntry<"blog">; availableOnLangs: CollectionEntry<"blog">[] }; const { Content, headings } = await Astro.props.article.render(); -const { article, availableOnLang } = Astro.props; +const { article, availableOnLangs } = Astro.props; --- - - { - availableOnLang.length > 1 && ( -
- {t("article.availableOn")}:{" "} - {availableOnLang - .filter((a) => !a.id.startsWith(`${pageLang}/`)) - .map(({ id, data: { title, pubDate } }) => ( - {`${ - languages[id.split("/")[0] as LanguageKeys] - }`} - ))} -
- ) - } + diff --git a/src/utils/article.ts b/src/utils/article.ts index 7702193..6e05e77 100644 --- a/src/utils/article.ts +++ b/src/utils/article.ts @@ -66,7 +66,7 @@ export function getUniqueTags(articles: CollectionEntry<"blog">[]): string[] { export type MarkdownHeadingToc = MarkdownHeading & { subheadings: MarkdownHeading[] }; -export function buildToc(headings: MarkdownHeading[]) { +export function buildToc(headings: MarkdownHeading[], maxDepth: number = 2) { const toc: MarkdownHeadingToc[] = []; const parentHeadings = new Map(); headings.forEach((h) => { @@ -74,7 +74,7 @@ export function buildToc(headings: MarkdownHeading[]) { parentHeadings.set(heading.depth, heading); if (heading.depth === 1) { toc.push(heading); - } else { + } else if (heading.depth <= maxDepth) { parentHeadings.get(heading.depth - 1).subheadings.push(heading); } });