From fe8e960b870ca5d71d7f9074cf3885a0b895ecb7 Mon Sep 17 00:00:00 2001 From: Sergey Yarkov Date: Sun, 28 Aug 2022 13:56:48 +0300 Subject: [PATCH 1/6] format --- .eslintrc.json | 6 ++++- .prettierrc.json | 2 +- public/assets/js/detect-theme.js | 12 ++++++---- public/assets/js/load-code-highlight.js | 8 ++++--- src/components/ArticleItem/ArticleItem.tsx | 10 ++++++-- src/components/ArticlesList/ArticlesList.tsx | 5 +++- src/components/Header/NavToggle/NavToggle.tsx | 24 ++++++++++++++++--- src/components/SearchInput/SearchInput.tsx | 8 ++++++- src/components/TagsList/TagsList.tsx | 7 +++++- .../ThemeSwticher/ThemeSwitcher.tsx | 10 ++++---- src/config.ts | 3 ++- src/i18n/en/ui.ts | 6 +++-- src/i18n/ru/ui.ts | 9 ++++--- src/i18n/utils.ts | 20 ++++++++++++---- src/pages/[...slug].astro | 23 ++++++++++++++---- src/pages/rss.xml.ts | 8 +++++-- src/services/ArticleService.ts | 4 +++- src/types/main.d.ts | 5 +++- src/utils/articles.ts | 14 ++++++++--- src/utils/string.ts | 4 +++- 20 files changed, 143 insertions(+), 45 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index d261713..0b65a70 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -3,7 +3,11 @@ "browser": true, "es2021": true }, - "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended", "plugin:solid/typescript"], + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "plugin:solid/typescript" + ], "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaVersion": "latest", diff --git a/.prettierrc.json b/.prettierrc.json index e7407ec..071de61 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -1,5 +1,5 @@ { - "printWidth": 150, + "printWidth": 100, "semi": true, "singleQuote": false, "tabWidth": 2, diff --git a/public/assets/js/detect-theme.js b/public/assets/js/detect-theme.js index d34ae2c..9d29c22 100644 --- a/public/assets/js/detect-theme.js +++ b/public/assets/js/detect-theme.js @@ -15,8 +15,10 @@ window.theme = (() => { document.documentElement.setAttribute("data-theme", window.theme); /* Sync with OS theme */ -window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", ({ matches: isDark }) => { - window.theme = isDark ? "dark" : "light"; - localStorage.setItem("theme", window.theme); - document.documentElement.setAttribute("data-theme", window.theme); -}); +window + .matchMedia("(prefers-color-scheme: dark)") + .addEventListener("change", ({ matches: isDark }) => { + window.theme = isDark ? "dark" : "light"; + localStorage.setItem("theme", window.theme); + document.documentElement.setAttribute("data-theme", window.theme); + }); diff --git a/public/assets/js/load-code-highlight.js b/public/assets/js/load-code-highlight.js index 9451820..6abed24 100644 --- a/public/assets/js/load-code-highlight.js +++ b/public/assets/js/load-code-highlight.js @@ -42,7 +42,9 @@ if (window.theme) { $head.appendChild($dark); window.addEventListener("onthemetoggled", ({ detail: newTheme }) => toggleMedia(newTheme)); - window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", ({ matches: isDark }) => { - return isDark ? toggleMedia("dark") : toggleMedia("light"); - }); + window + .matchMedia("(prefers-color-scheme: dark)") + .addEventListener("change", ({ matches: isDark }) => { + return isDark ? toggleMedia("dark") : toggleMedia("light"); + }); } diff --git a/src/components/ArticleItem/ArticleItem.tsx b/src/components/ArticleItem/ArticleItem.tsx index 4ba2e3c..a64d1b9 100644 --- a/src/components/ArticleItem/ArticleItem.tsx +++ b/src/components/ArticleItem/ArticleItem.tsx @@ -14,13 +14,19 @@ export const ArticleItem: Component = (props) => { const hrefLangPrefix = props.data.lang && props.data.lang !== DEFAULT_LANGUAGE ? "/en" : ""; return ( diff --git a/src/components/ArticlesList/ArticlesList.tsx b/src/components/ArticlesList/ArticlesList.tsx index b059d0c..9b7356c 100644 --- a/src/components/ArticlesList/ArticlesList.tsx +++ b/src/components/ArticlesList/ArticlesList.tsx @@ -84,7 +84,10 @@ const ArticlesList: Component = (props) => { return (

{year}

- } /> + } + />
); }} diff --git a/src/components/Header/NavToggle/NavToggle.tsx b/src/components/Header/NavToggle/NavToggle.tsx index 712149c..f12ca34 100644 --- a/src/components/Header/NavToggle/NavToggle.tsx +++ b/src/components/Header/NavToggle/NavToggle.tsx @@ -4,13 +4,25 @@ import { createSignal, createEffect } from "solid-js"; import "./NavToggle.scss"; const MenuIcon: Component = () => ( - + ); const CloseIcon: Component = () => ( - + ); @@ -32,7 +44,13 @@ const NavToggle: Component = () => { }); return ( -
- + )} diff --git a/src/components/ThemeSwticher/ThemeSwitcher.tsx b/src/components/ThemeSwticher/ThemeSwitcher.tsx index a28c970..d6dd099 100644 --- a/src/components/ThemeSwticher/ThemeSwitcher.tsx +++ b/src/components/ThemeSwticher/ThemeSwitcher.tsx @@ -43,10 +43,12 @@ const ThemeSwitcher: Component = () => { if (window.theme) { setTheme(window.theme); /* Update theme state on changing OS theme */ - window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", ({ matches: isDark }) => { - const theme = isDark ? "dark" : "light"; - setTheme(theme); - }); + window + .matchMedia("(prefers-color-scheme: dark)") + .addEventListener("change", ({ matches: isDark }) => { + const theme = isDark ? "dark" : "light"; + setTheme(theme); + }); } }); diff --git a/src/config.ts b/src/config.ts index 153c297..1c0c6a8 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,7 +1,8 @@ export const DEFAULT_LANGUAGE: LanguageKeys = "ru"; /* Show banner about website development */ -export const IS_SITE_UNDER_CONSTRUCTION = import.meta.env.IS_SITE_UNDER_CONSTRUCTION === "true" ? true : false; +export const IS_SITE_UNDER_CONSTRUCTION = + import.meta.env.IS_SITE_UNDER_CONSTRUCTION === "true" ? true : false; export const SITE_METADATA: SiteMetadataType = { title: "Sergey Yarkov", diff --git a/src/i18n/en/ui.ts b/src/i18n/en/ui.ts index 28b5028..49e47f0 100644 --- a/src/i18n/en/ui.ts +++ b/src/i18n/en/ui.ts @@ -13,8 +13,10 @@ export default { "pageTitle.projects": "Projects", "pageTitle.contacts": "Contacts", /* Page descriptions */ - "pageDescription.articles": "Technical articles, tutorials and various reference materials related to IT topics can be found here.", - "pageDescription.projects": "A few of my main projects that have been developed and published in open access.", + "pageDescription.articles": + "Technical articles, tutorials and various reference materials related to IT topics can be found here.", + "pageDescription.projects": + "A few of my main projects that have been developed and published in open access.", "pageDescription.contacts": "Use the feedback form or write to me on social networks.", /* Navigation */ "navigation.articles": "Articles", diff --git a/src/i18n/ru/ui.ts b/src/i18n/ru/ui.ts index e71f55e..8485f4e 100644 --- a/src/i18n/ru/ui.ts +++ b/src/i18n/ru/ui.ts @@ -13,9 +13,12 @@ export default { "pageTitle.projects": "Проекты", "pageTitle.contacts": "Контакты", /* Page descriptions */ - "pageDescription.articles": "Технические статьи, туториалы и различные справочные материалы которые связаны с IT тематикой находятся здесь.", - "pageDescription.projects": "Несколько моих основных проектов которые были разработаны и выложены в открытый доступ.", - "pageDescription.contacts": "Воспользуйтесь формой обратной связи или напишите мне в социальные сети.", + "pageDescription.articles": + "Технические статьи, туториалы и различные справочные материалы которые связаны с IT тематикой находятся здесь.", + "pageDescription.projects": + "Несколько моих основных проектов которые были разработаны и выложены в открытый доступ.", + "pageDescription.contacts": + "Воспользуйтесь формой обратной связи или напишите мне в социальные сети.", /* Navigation */ "navigation.articles": "Статьи", "navigation.projects": "Проекты", diff --git a/src/i18n/utils.ts b/src/i18n/utils.ts index 0273a25..f238ce0 100644 --- a/src/i18n/utils.ts +++ b/src/i18n/utils.ts @@ -3,9 +3,14 @@ import * as utils from "@utils/url"; import { DEFAULT_LANGUAGE } from "@root/config"; import languages from "./languages"; -type TranslatedArticlesType = Record> | Record>; +type TranslatedArticlesType = Record< + string, + Record> | Record +>; -export function formatArticlesByLangs(data: Record>): TranslatedArticlesType { +export function formatArticlesByLangs( + data: Record> +): TranslatedArticlesType { const modules: TranslatedArticlesType = {}; for (const module of Object.values(data)) { @@ -33,15 +38,20 @@ function transformExports(modules: Record) { return translations; } -const translations = transformExports(import.meta.glob("./*/ui.ts", { eager: true })); +const translations = transformExports( + import.meta.glob("./*/ui.ts", { eager: true }) +); export function translate(key: UIDictionaryKeys, lang: LanguageKeys): string | undefined { - const string: string | undefined = translations[lang]?.[key] || translations[DEFAULT_LANGUAGE][key]; + const string: string | undefined = + translations[lang]?.[key] || translations[DEFAULT_LANGUAGE][key]; if (string === undefined) console.log(`Cannot find any string for translation key "${key}".`); return string; } -export function useTranslation(Astro: Readonly): (key: UIDictionaryKeys) => string | undefined { +export function useTranslation( + Astro: Readonly +): (key: UIDictionaryKeys) => string | undefined { const lang: LanguageKeys = utils.getLanguageFromURL(Astro.url.pathname) as LanguageKeys; return (key: UIDictionaryKeys) => translate(key, lang); } diff --git a/src/pages/[...slug].astro b/src/pages/[...slug].astro index 723a907..201e62a 100644 --- a/src/pages/[...slug].astro +++ b/src/pages/[...slug].astro @@ -17,7 +17,9 @@ export interface Props { } export async function getStaticPaths() { - const modules = import.meta.glob>("../../content/articles/**/*.mdx", { eager: true }); + const modules = import.meta.glob>("../../content/articles/**/*.mdx", { + eager: true, + }); const entries = Object.keys(modules).map((key) => [key, key.split("/").slice(6)[0]]); const formatted = formatArticlesByLangs(modules); @@ -26,9 +28,14 @@ export async function getStaticPaths() { const article = modules[key]; const dirName = key.split("/").at(-3); const published_at = new Date(article.frontmatter.published_at).toLocaleDateString("en-CA"); - const slug = `${lang !== DEFAULT_LANGUAGE ? `${lang}/` : ""}blog/${published_at}/${article.frontmatter.slug}`; + const slug = `${lang !== DEFAULT_LANGUAGE ? `${lang}/` : ""}blog/${published_at}/${ + article.frontmatter.slug + }`; - return { params: { slug }, props: { article, alternateLangs: Object.keys(formatted[dirName]) } }; + return { + params: { slug }, + props: { article, alternateLangs: Object.keys(formatted[dirName]) }, + }; }) .filter(({ props: { article } }) => !article.frontmatter.draft); } @@ -49,7 +56,15 @@ const { pathname } = Astro.url; {alternateLangs .filter((lang) => lang !== siteLang) .map((lang) => ( - {languages[lang]} + + {languages[lang]} + )) .reduce((prev, curr) => [prev, ", ", curr])}
diff --git a/src/pages/rss.xml.ts b/src/pages/rss.xml.ts index 3052a0e..925c54a 100644 --- a/src/pages/rss.xml.ts +++ b/src/pages/rss.xml.ts @@ -4,7 +4,9 @@ import rss from "@astrojs/rss"; import { DEFAULT_LANGUAGE, SITE_METADATA } from "@root/config"; import * as utils from "@i18n/utils"; -const data = import.meta.glob>("../../content/articles/**/*.mdx", { eager: true }); +const data = import.meta.glob>("../../content/articles/**/*.mdx", { + eager: true, +}); const articles = Object.values(utils.formatArticlesByLangs(data)); const items = []; @@ -20,7 +22,9 @@ for (const key of Object.keys(articles)) { new Date(published_at).toLocaleDateString("en-CA") + `/${slug}/`, title, - description: `${description}${coverImage !== undefined ? `${title}` : ""}`, + description: `${description}${ + coverImage !== undefined ? `${title}` : "" + }`, pubDate: published_at, customData: `${lang}`, }); diff --git a/src/services/ArticleService.ts b/src/services/ArticleService.ts index c6fedbd..886530a 100644 --- a/src/services/ArticleService.ts +++ b/src/services/ArticleService.ts @@ -4,7 +4,9 @@ import { getLanguageFromURL } from "@utils/url"; class ArticleService { public getTranslatedArticles(Astro: Readonly): MDXInstance[] { - const data = import.meta.glob>("../../content/articles/**/*.mdx", { eager: true }); + const data = import.meta.glob>("../../content/articles/**/*.mdx", { + eager: true, + }); const modules = formatArticlesByLangs(data); const siteLang = getLanguageFromURL(Astro.url.pathname); const articles: MDXInstance[] = []; diff --git a/src/types/main.d.ts b/src/types/main.d.ts index a0fcc75..eee38fa 100644 --- a/src/types/main.d.ts +++ b/src/types/main.d.ts @@ -5,7 +5,10 @@ export {}; declare global { interface Window { theme?: ThemeModeType | undefined; - addEventListener(type: K, listener: (this: Window, ev: CustomEventMap[K]) => void): void; + addEventListener( + type: K, + listener: (this: Window, ev: CustomEventMap[K]) => void + ): void; } interface CustomEventMap { diff --git a/src/utils/articles.ts b/src/utils/articles.ts index 7ea06ce..5bf867b 100644 --- a/src/utils/articles.ts +++ b/src/utils/articles.ts @@ -12,7 +12,9 @@ export const transformArticles = (articles: MDXInstance[]): Article })); export const sortArtcilesByDate = (articles: ArticleType[]): ArticleType[] => { - return articles.sort((a, b) => new Date(b.published_at).valueOf() - new Date(a.published_at).valueOf()); + return articles.sort( + (a, b) => new Date(b.published_at).valueOf() - new Date(a.published_at).valueOf() + ); }; /** @@ -31,7 +33,10 @@ export const formatToArticleBlocks = (articles: ArticleType[]): ArticleBlockType return blocks; }; -export const findArticlesBySearch = (search: string, articles: ArticleBlockType): ArticleBlockType => { +export const findArticlesBySearch = ( + search: string, + articles: ArticleBlockType +): ArticleBlockType => { const matched: Array = []; search = search.toLocaleLowerCase(); @@ -49,7 +54,10 @@ export const findArticlesBySearch = (search: string, articles: ArticleBlockType) return formatToArticleBlocks(matched); }; -export const findArticlesByTags = (tags: string[], articles: ArticleBlockType): ArticleBlockType => { +export const findArticlesByTags = ( + tags: string[], + articles: ArticleBlockType +): ArticleBlockType => { const matched: Array = []; for (const year in articles) { diff --git a/src/utils/string.ts b/src/utils/string.ts index 085aa38..4d0df9f 100644 --- a/src/utils/string.ts +++ b/src/utils/string.ts @@ -7,5 +7,7 @@ export function isEmail(email: string): boolean { } export function isURL(url: string): boolean { - return new RegExp(/(http|ftp|https):\/\/([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:\\/~+#-]*[\w@?^=%&\\/~+#-])/).test(url); + return new RegExp( + /(http|ftp|https):\/\/([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:\\/~+#-]*[\w@?^=%&\\/~+#-])/ + ).test(url); } From fbb047e8b78edf2d476208b6e170ee2fff7c5fa2 Mon Sep 17 00:00:00 2001 From: Sergey Yarkov Date: Sun, 28 Aug 2022 14:00:38 +0300 Subject: [PATCH 2/6] format --- .eslintrc.json | 6 +-- .prettierrc.json | 2 +- public/assets/js/detect-theme.js | 12 +++--- public/assets/js/load-code-highlight.js | 8 ++-- src/components/ArticleItem/ArticleItem.tsx | 6 +-- src/components/Header/NavToggle/NavToggle.tsx | 24 ++--------- src/components/SearchInput/SearchInput.tsx | 8 +--- src/components/TagsList/TagsList.tsx | 7 +-- .../ThemeSwticher/ThemeSwitcher.tsx | 10 ++--- src/config.ts | 43 ++++++++++++++----- src/i18n/en/ui.ts | 3 +- src/i18n/ru/ui.ts | 6 +-- src/i18n/utils.ts | 20 +++------ src/pages/rss.xml.ts | 4 +- src/types/main.d.ts | 10 ++++- src/utils/articles.ts | 14 ++---- src/utils/string.ts | 6 +-- 17 files changed, 78 insertions(+), 111 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 0b65a70..d261713 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -3,11 +3,7 @@ "browser": true, "es2021": true }, - "extends": [ - "eslint:recommended", - "plugin:@typescript-eslint/recommended", - "plugin:solid/typescript" - ], + "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended", "plugin:solid/typescript"], "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaVersion": "latest", diff --git a/.prettierrc.json b/.prettierrc.json index 071de61..f3d832f 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -1,5 +1,5 @@ { - "printWidth": 100, + "printWidth": 120, "semi": true, "singleQuote": false, "tabWidth": 2, diff --git a/public/assets/js/detect-theme.js b/public/assets/js/detect-theme.js index 9d29c22..d34ae2c 100644 --- a/public/assets/js/detect-theme.js +++ b/public/assets/js/detect-theme.js @@ -15,10 +15,8 @@ window.theme = (() => { document.documentElement.setAttribute("data-theme", window.theme); /* Sync with OS theme */ -window - .matchMedia("(prefers-color-scheme: dark)") - .addEventListener("change", ({ matches: isDark }) => { - window.theme = isDark ? "dark" : "light"; - localStorage.setItem("theme", window.theme); - document.documentElement.setAttribute("data-theme", window.theme); - }); +window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", ({ matches: isDark }) => { + window.theme = isDark ? "dark" : "light"; + localStorage.setItem("theme", window.theme); + document.documentElement.setAttribute("data-theme", window.theme); +}); diff --git a/public/assets/js/load-code-highlight.js b/public/assets/js/load-code-highlight.js index 6abed24..9451820 100644 --- a/public/assets/js/load-code-highlight.js +++ b/public/assets/js/load-code-highlight.js @@ -42,9 +42,7 @@ if (window.theme) { $head.appendChild($dark); window.addEventListener("onthemetoggled", ({ detail: newTheme }) => toggleMedia(newTheme)); - window - .matchMedia("(prefers-color-scheme: dark)") - .addEventListener("change", ({ matches: isDark }) => { - return isDark ? toggleMedia("dark") : toggleMedia("light"); - }); + window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", ({ matches: isDark }) => { + return isDark ? toggleMedia("dark") : toggleMedia("light"); + }); } diff --git a/src/components/ArticleItem/ArticleItem.tsx b/src/components/ArticleItem/ArticleItem.tsx index a64d1b9..0c0e074 100644 --- a/src/components/ArticleItem/ArticleItem.tsx +++ b/src/components/ArticleItem/ArticleItem.tsx @@ -15,9 +15,9 @@ export const ArticleItem: Component = (props) => { return (

{props.data.title}

diff --git a/src/components/Header/NavToggle/NavToggle.tsx b/src/components/Header/NavToggle/NavToggle.tsx index f12ca34..712149c 100644 --- a/src/components/Header/NavToggle/NavToggle.tsx +++ b/src/components/Header/NavToggle/NavToggle.tsx @@ -4,25 +4,13 @@ import { createSignal, createEffect } from "solid-js"; import "./NavToggle.scss"; const MenuIcon: Component = () => ( - + ); const CloseIcon: Component = () => ( - + ); @@ -44,13 +32,7 @@ const NavToggle: Component = () => { }); return ( -
- + )} diff --git a/src/components/ThemeSwticher/ThemeSwitcher.tsx b/src/components/ThemeSwticher/ThemeSwitcher.tsx index d6dd099..a28c970 100644 --- a/src/components/ThemeSwticher/ThemeSwitcher.tsx +++ b/src/components/ThemeSwticher/ThemeSwitcher.tsx @@ -43,12 +43,10 @@ const ThemeSwitcher: Component = () => { if (window.theme) { setTheme(window.theme); /* Update theme state on changing OS theme */ - window - .matchMedia("(prefers-color-scheme: dark)") - .addEventListener("change", ({ matches: isDark }) => { - const theme = isDark ? "dark" : "light"; - setTheme(theme); - }); + window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", ({ matches: isDark }) => { + const theme = isDark ? "dark" : "light"; + setTheme(theme); + }); } }); diff --git a/src/config.ts b/src/config.ts index 1c0c6a8..4cec084 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,8 +1,7 @@ export const DEFAULT_LANGUAGE: LanguageKeys = "ru"; /* Show banner about website development */ -export const IS_SITE_UNDER_CONSTRUCTION = - import.meta.env.IS_SITE_UNDER_CONSTRUCTION === "true" ? true : false; +export const IS_SITE_UNDER_CONSTRUCTION = import.meta.env.IS_SITE_UNDER_CONSTRUCTION === "true" ? true : false; export const SITE_METADATA: SiteMetadataType = { title: "Sergey Yarkov", @@ -15,10 +14,19 @@ export const SITE_METADATA: SiteMetadataType = { telegramUrl: "https://t.me/sergeyyarkov", }, nav: [ - { key: "navigation.articles", url: "/articles/" }, - { key: "navigation.projects", url: "/projects/" }, + { + key: "navigation.articles", + url: "/articles/", + }, + { + key: "navigation.projects", + url: "/projects/", + }, { key: "navigation.about", url: "/about/" }, - { key: "navigation.contacts", url: "/contacts/" }, + { + key: "navigation.contacts", + url: "/contacts/", + }, ], projects: [ { @@ -113,11 +121,20 @@ export const SITE_METADATA: SiteMetadataType = { en: "Programming", }, list: [ - { icon: "nodejs", name: "Javascript/Typescript" }, - { icon: "language-c", name: "C Language" }, + { + icon: "nodejs", + name: "Javascript/Typescript", + }, + { + icon: "language-c", + name: "C Language", + }, { icon: "mysql", name: "SQL" }, { icon: "graphql", name: "GraphQL" }, - { icon: "avr", name: "AVR instruction set" }, + { + icon: "avr", + name: "AVR instruction set", + }, ], }, { @@ -142,7 +159,10 @@ export const SITE_METADATA: SiteMetadataType = { list: [ { icon: "nodejs", name: "Node.js" }, { icon: "docker", name: "Docker" }, - { icon: "git-branch", name: "Git/gitflow" }, + { + icon: "git-branch", + name: "Git/gitflow", + }, { icon: "sass", name: "SASS" }, { icon: "webpack", name: "Webpack" }, { icon: "vite", name: "Vite.js" }, @@ -154,7 +174,10 @@ export const SITE_METADATA: SiteMetadataType = { en: "Databases", }, list: [ - { icon: "postgresql", name: "PostgreSQL" }, + { + icon: "postgresql", + name: "PostgreSQL", + }, { icon: "mongodb", name: "MongoDB" }, { icon: "redis", name: "Redis" }, ], diff --git a/src/i18n/en/ui.ts b/src/i18n/en/ui.ts index 49e47f0..a140144 100644 --- a/src/i18n/en/ui.ts +++ b/src/i18n/en/ui.ts @@ -15,8 +15,7 @@ export default { /* Page descriptions */ "pageDescription.articles": "Technical articles, tutorials and various reference materials related to IT topics can be found here.", - "pageDescription.projects": - "A few of my main projects that have been developed and published in open access.", + "pageDescription.projects": "A few of my main projects that have been developed and published in open access.", "pageDescription.contacts": "Use the feedback form or write to me on social networks.", /* Navigation */ "navigation.articles": "Articles", diff --git a/src/i18n/ru/ui.ts b/src/i18n/ru/ui.ts index 8485f4e..f7ad02c 100644 --- a/src/i18n/ru/ui.ts +++ b/src/i18n/ru/ui.ts @@ -15,10 +15,8 @@ export default { /* Page descriptions */ "pageDescription.articles": "Технические статьи, туториалы и различные справочные материалы которые связаны с IT тематикой находятся здесь.", - "pageDescription.projects": - "Несколько моих основных проектов которые были разработаны и выложены в открытый доступ.", - "pageDescription.contacts": - "Воспользуйтесь формой обратной связи или напишите мне в социальные сети.", + "pageDescription.projects": "Несколько моих основных проектов которые были разработаны и выложены в открытый доступ.", + "pageDescription.contacts": "Воспользуйтесь формой обратной связи или напишите мне в социальные сети.", /* Navigation */ "navigation.articles": "Статьи", "navigation.projects": "Проекты", diff --git a/src/i18n/utils.ts b/src/i18n/utils.ts index f238ce0..0273a25 100644 --- a/src/i18n/utils.ts +++ b/src/i18n/utils.ts @@ -3,14 +3,9 @@ import * as utils from "@utils/url"; import { DEFAULT_LANGUAGE } from "@root/config"; import languages from "./languages"; -type TranslatedArticlesType = Record< - string, - Record> | Record ->; +type TranslatedArticlesType = Record> | Record>; -export function formatArticlesByLangs( - data: Record> -): TranslatedArticlesType { +export function formatArticlesByLangs(data: Record>): TranslatedArticlesType { const modules: TranslatedArticlesType = {}; for (const module of Object.values(data)) { @@ -38,20 +33,15 @@ function transformExports(modules: Record) { return translations; } -const translations = transformExports( - import.meta.glob("./*/ui.ts", { eager: true }) -); +const translations = transformExports(import.meta.glob("./*/ui.ts", { eager: true })); export function translate(key: UIDictionaryKeys, lang: LanguageKeys): string | undefined { - const string: string | undefined = - translations[lang]?.[key] || translations[DEFAULT_LANGUAGE][key]; + const string: string | undefined = translations[lang]?.[key] || translations[DEFAULT_LANGUAGE][key]; if (string === undefined) console.log(`Cannot find any string for translation key "${key}".`); return string; } -export function useTranslation( - Astro: Readonly -): (key: UIDictionaryKeys) => string | undefined { +export function useTranslation(Astro: Readonly): (key: UIDictionaryKeys) => string | undefined { const lang: LanguageKeys = utils.getLanguageFromURL(Astro.url.pathname) as LanguageKeys; return (key: UIDictionaryKeys) => translate(key, lang); } diff --git a/src/pages/rss.xml.ts b/src/pages/rss.xml.ts index 925c54a..7815d69 100644 --- a/src/pages/rss.xml.ts +++ b/src/pages/rss.xml.ts @@ -22,9 +22,7 @@ for (const key of Object.keys(articles)) { new Date(published_at).toLocaleDateString("en-CA") + `/${slug}/`, title, - description: `${description}${ - coverImage !== undefined ? `${title}` : "" - }`, + description: `${description}${coverImage !== undefined ? `${title}` : ""}`, pubDate: published_at, customData: `${lang}`, }); diff --git a/src/types/main.d.ts b/src/types/main.d.ts index eee38fa..b5af401 100644 --- a/src/types/main.d.ts +++ b/src/types/main.d.ts @@ -28,7 +28,10 @@ declare global { githubUrl: string; telegramUrl: string; }; - nav: Array<{ key: UIDictionaryKeys; url: string }>; + nav: Array<{ + key: UIDictionaryKeys; + url: string; + }>; projects: Array; skills: Array; }; @@ -57,7 +60,10 @@ declare global { type SkillsType = { title: Record; - list: Array<{ icon?: string | undefined; name: string }>; + list: Array<{ + icon?: string | undefined; + name: string; + }>; }; type ContactFieldsType = { diff --git a/src/utils/articles.ts b/src/utils/articles.ts index 5bf867b..7ea06ce 100644 --- a/src/utils/articles.ts +++ b/src/utils/articles.ts @@ -12,9 +12,7 @@ export const transformArticles = (articles: MDXInstance[]): Article })); export const sortArtcilesByDate = (articles: ArticleType[]): ArticleType[] => { - return articles.sort( - (a, b) => new Date(b.published_at).valueOf() - new Date(a.published_at).valueOf() - ); + return articles.sort((a, b) => new Date(b.published_at).valueOf() - new Date(a.published_at).valueOf()); }; /** @@ -33,10 +31,7 @@ export const formatToArticleBlocks = (articles: ArticleType[]): ArticleBlockType return blocks; }; -export const findArticlesBySearch = ( - search: string, - articles: ArticleBlockType -): ArticleBlockType => { +export const findArticlesBySearch = (search: string, articles: ArticleBlockType): ArticleBlockType => { const matched: Array = []; search = search.toLocaleLowerCase(); @@ -54,10 +49,7 @@ export const findArticlesBySearch = ( return formatToArticleBlocks(matched); }; -export const findArticlesByTags = ( - tags: string[], - articles: ArticleBlockType -): ArticleBlockType => { +export const findArticlesByTags = (tags: string[], articles: ArticleBlockType): ArticleBlockType => { const matched: Array = []; for (const year in articles) { diff --git a/src/utils/string.ts b/src/utils/string.ts index 4d0df9f..026d02a 100644 --- a/src/utils/string.ts +++ b/src/utils/string.ts @@ -7,7 +7,7 @@ export function isEmail(email: string): boolean { } export function isURL(url: string): boolean { - return new RegExp( - /(http|ftp|https):\/\/([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:\\/~+#-]*[\w@?^=%&\\/~+#-])/ - ).test(url); + return new RegExp(/(http|ftp|https):\/\/([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:\\/~+#-]*[\w@?^=%&\\/~+#-])/).test( + url + ); } From 01bb18b774137e3739baa0df4ef696cb36fa1470 Mon Sep 17 00:00:00 2001 From: Sergey Yarkov Date: Sun, 28 Aug 2022 14:27:47 +0300 Subject: [PATCH 3/6] format --- .prettierrc.json | 2 +- package.json | 2 +- src/components/ArticleItem/ArticleItem.tsx | 10 ++++++++-- src/components/ArticlePost/ArticlePost.astro | 8 ++++++-- src/components/ArticlesList/ArticlesList.tsx | 5 ++++- src/components/BaseHead.astro | 16 ++++++++++++++-- src/components/ContactForm/ContactForm.astro | 9 ++++++++- src/components/Header/Header.astro | 5 ++++- src/i18n/en/ui.ts | 3 ++- src/i18n/ru/ui.ts | 3 ++- src/layouts/default.astro | 6 +++++- src/pages/[...slug].astro | 4 +++- src/templates/Articles.astro | 7 ++++++- src/types/main.d.ts | 5 ++++- src/utils/string.ts | 4 +++- 15 files changed, 71 insertions(+), 18 deletions(-) diff --git a/.prettierrc.json b/.prettierrc.json index e7407ec..f3d832f 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -1,5 +1,5 @@ { - "printWidth": 150, + "printWidth": 120, "semi": true, "singleQuote": false, "tabWidth": 2, diff --git a/package.json b/package.json index 4767fe8..1f6ee7a 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "start": "astro dev", "build": "astro build", "preview": "astro preview --host", - "format": "prettier --write \"**/*.{js,jsx,ts,tsx,json,md,mdx}\"", + "format": "prettier --write ./src/\"**/*.{js,jsx,ts,tsx,json,md,mdx,astro}\"", "lint": "eslint '**/*.{js,mjs,ts,tsx}'" }, "devDependencies": { diff --git a/src/components/ArticleItem/ArticleItem.tsx b/src/components/ArticleItem/ArticleItem.tsx index 4ba2e3c..0c0e074 100644 --- a/src/components/ArticleItem/ArticleItem.tsx +++ b/src/components/ArticleItem/ArticleItem.tsx @@ -14,13 +14,19 @@ export const ArticleItem: Component = (props) => { const hrefLangPrefix = props.data.lang && props.data.lang !== DEFAULT_LANGUAGE ? "/en" : ""; return ( diff --git a/src/components/ArticlePost/ArticlePost.astro b/src/components/ArticlePost/ArticlePost.astro index 223098b..c67e59b 100644 --- a/src/components/ArticlePost/ArticlePost.astro +++ b/src/components/ArticlePost/ArticlePost.astro @@ -21,7 +21,9 @@ const { title, coverImage, tags, author, published_at } = data; { tags.map((tag) => (
  • - +
  • )) } @@ -31,7 +33,9 @@ const { title, coverImage, tags, author, published_at } = data;

    {title}

    - +
    { diff --git a/src/components/ArticlesList/ArticlesList.tsx b/src/components/ArticlesList/ArticlesList.tsx index b059d0c..9b7356c 100644 --- a/src/components/ArticlesList/ArticlesList.tsx +++ b/src/components/ArticlesList/ArticlesList.tsx @@ -84,7 +84,10 @@ const ArticlesList: Component = (props) => { return (

    {year}

    - } /> + } + />
    ); }} diff --git a/src/components/BaseHead.astro b/src/components/BaseHead.astro index ae4de95..5db2629 100644 --- a/src/components/BaseHead.astro +++ b/src/components/BaseHead.astro @@ -30,8 +30,20 @@ const { title = SITE_METADATA.title, description, canonicalUrl } = Astro.props a - - + + diff --git a/src/components/ContactForm/ContactForm.astro b/src/components/ContactForm/ContactForm.astro index c28cd56..44165e0 100644 --- a/src/components/ContactForm/ContactForm.astro +++ b/src/components/ContactForm/ContactForm.astro @@ -19,7 +19,14 @@ const t = useTranslation(Astro);
    - + diff --git a/src/components/Header/Header.astro b/src/components/Header/Header.astro index 63536d1..86938d0 100644 --- a/src/components/Header/Header.astro +++ b/src/components/Header/Header.astro @@ -24,7 +24,10 @@ const { pathname } = Astro.url; { nav.map((link) => (
  • - +
  • diff --git a/src/i18n/en/ui.ts b/src/i18n/en/ui.ts index 28b5028..a140144 100644 --- a/src/i18n/en/ui.ts +++ b/src/i18n/en/ui.ts @@ -13,7 +13,8 @@ export default { "pageTitle.projects": "Projects", "pageTitle.contacts": "Contacts", /* Page descriptions */ - "pageDescription.articles": "Technical articles, tutorials and various reference materials related to IT topics can be found here.", + "pageDescription.articles": + "Technical articles, tutorials and various reference materials related to IT topics can be found here.", "pageDescription.projects": "A few of my main projects that have been developed and published in open access.", "pageDescription.contacts": "Use the feedback form or write to me on social networks.", /* Navigation */ diff --git a/src/i18n/ru/ui.ts b/src/i18n/ru/ui.ts index e71f55e..f7ad02c 100644 --- a/src/i18n/ru/ui.ts +++ b/src/i18n/ru/ui.ts @@ -13,7 +13,8 @@ export default { "pageTitle.projects": "Проекты", "pageTitle.contacts": "Контакты", /* Page descriptions */ - "pageDescription.articles": "Технические статьи, туториалы и различные справочные материалы которые связаны с IT тематикой находятся здесь.", + "pageDescription.articles": + "Технические статьи, туториалы и различные справочные материалы которые связаны с IT тематикой находятся здесь.", "pageDescription.projects": "Несколько моих основных проектов которые были разработаны и выложены в открытый доступ.", "pageDescription.contacts": "Воспользуйтесь формой обратной связи или напишите мне в социальные сети.", /* Navigation */ diff --git a/src/layouts/default.astro b/src/layouts/default.astro index 93f0ce9..e32b72a 100644 --- a/src/layouts/default.astro +++ b/src/layouts/default.astro @@ -16,7 +16,11 @@ const { title, description, lang = "ru", noIndex = false, canonicalUrl } = Astro --- - + {noIndex && } diff --git a/src/pages/[...slug].astro b/src/pages/[...slug].astro index 723a907..8e0a3ca 100644 --- a/src/pages/[...slug].astro +++ b/src/pages/[...slug].astro @@ -49,7 +49,9 @@ const { pathname } = Astro.url; {alternateLangs .filter((lang) => lang !== siteLang) .map((lang) => ( - {languages[lang]} + + {languages[lang]} + )) .reduce((prev, curr) => [prev, ", ", curr])} diff --git a/src/templates/Articles.astro b/src/templates/Articles.astro index e53d204..0778c86 100644 --- a/src/templates/Articles.astro +++ b/src/templates/Articles.astro @@ -15,7 +15,12 @@ const articles = transformArticles(data); const canonicalUrl = new URL(Astro.url.pathname, Astro.site); --- - +
    (type: K, listener: (this: Window, ev: CustomEventMap[K]) => void): void; + addEventListener( + type: K, + listener: (this: Window, ev: CustomEventMap[K]) => void + ): void; } interface CustomEventMap { diff --git a/src/utils/string.ts b/src/utils/string.ts index 085aa38..026d02a 100644 --- a/src/utils/string.ts +++ b/src/utils/string.ts @@ -7,5 +7,7 @@ export function isEmail(email: string): boolean { } export function isURL(url: string): boolean { - return new RegExp(/(http|ftp|https):\/\/([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:\\/~+#-]*[\w@?^=%&\\/~+#-])/).test(url); + return new RegExp(/(http|ftp|https):\/\/([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:\\/~+#-]*[\w@?^=%&\\/~+#-])/).test( + url + ); } From 3f427306594358bbbc5666d79c0fbd040b508ba1 Mon Sep 17 00:00:00 2001 From: Sergey Yarkov Date: Sun, 28 Aug 2022 14:31:21 +0300 Subject: [PATCH 4/6] fix --- src/pages/[...slug].astro | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/src/pages/[...slug].astro b/src/pages/[...slug].astro index 4b3a9bc..8e0a3ca 100644 --- a/src/pages/[...slug].astro +++ b/src/pages/[...slug].astro @@ -17,9 +17,7 @@ export interface Props { } export async function getStaticPaths() { - const modules = import.meta.glob>("../../content/articles/**/*.mdx", { - eager: true, - }); + const modules = import.meta.glob>("../../content/articles/**/*.mdx", { eager: true }); const entries = Object.keys(modules).map((key) => [key, key.split("/").slice(6)[0]]); const formatted = formatArticlesByLangs(modules); @@ -28,14 +26,9 @@ export async function getStaticPaths() { const article = modules[key]; const dirName = key.split("/").at(-3); const published_at = new Date(article.frontmatter.published_at).toLocaleDateString("en-CA"); - const slug = `${lang !== DEFAULT_LANGUAGE ? `${lang}/` : ""}blog/${published_at}/${ - article.frontmatter.slug - }`; + const slug = `${lang !== DEFAULT_LANGUAGE ? `${lang}/` : ""}blog/${published_at}/${article.frontmatter.slug}`; - return { - params: { slug }, - props: { article, alternateLangs: Object.keys(formatted[dirName]) }, - }; + return { params: { slug }, props: { article, alternateLangs: Object.keys(formatted[dirName]) } }; }) .filter(({ props: { article } }) => !article.frontmatter.draft); } @@ -49,6 +42,20 @@ const { pathname } = Astro.url; --- - + { + alternateLangs.length > 1 && ( +
    + {t("article.availableOn")}: + {alternateLangs + .filter((lang) => lang !== siteLang) + .map((lang) => ( + + {languages[lang]} + + )) + .reduce((prev, curr) => [prev, ", ", curr])} +
    + ) + }
    From c2523dd294e906b4d884345eedded45b786c063c Mon Sep 17 00:00:00 2001 From: Sergey Yarkov Date: Sun, 28 Aug 2022 18:39:16 +0300 Subject: [PATCH 5/6] fixed i18n --- astro.config.mjs | 18 +++++++---- .../AlternateLangLink/AlternateLangLink.astro | 30 +++++++++++++++++++ src/components/AlternateLangLink/index.ts | 1 + src/components/ArticleItem/ArticleItem.tsx | 2 +- .../LanguageSelect/LanguageSelect.astro | 14 +++++++-- src/config.ts | 2 ++ src/i18n/languages.ts | 1 + src/i18n/utils.ts | 4 +-- src/pages/[...slug].astro | 9 ++---- src/templates/About.astro | 15 ++++++++-- src/types/main.d.ts | 5 ++-- src/utils/url.ts | 4 +++ 12 files changed, 81 insertions(+), 24 deletions(-) create mode 100644 src/components/AlternateLangLink/AlternateLangLink.astro create mode 100644 src/components/AlternateLangLink/index.ts diff --git a/astro.config.mjs b/astro.config.mjs index 0c6ce25..9991a20 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -1,8 +1,3 @@ -import { defineConfig } from "astro/config"; -import { h } from "hastscript"; -import { toString } from "hast-util-to-string"; -import { escape } from "html-escaper"; - /** * Integrations */ @@ -24,6 +19,14 @@ import remarkSmartypants from "remark-smartypants"; import rehypeSlug from "rehype-slug"; import rehypeAutolinkHeadings from "rehype-autolink-headings"; +/** + * Other required modules + */ +import { defineConfig } from "astro/config"; +import { h } from "hastscript"; +import { toString } from "hast-util-to-string"; +import { escape } from "html-escaper"; + const createAnchorLabel = (heading) => { const node = h("span.anchor-label", escape(heading)); node.properties["is:raw"] = true; @@ -41,11 +44,14 @@ export default defineConfig({ locales: { ru: "ru", en: "en", + de: "de", }, }, }), image(), - compress(), + compress({ + img: false, + }), mdx({ remarkPlugins: [remarkGfm, remarkSmartypants], rehypePlugins: [ diff --git a/src/components/AlternateLangLink/AlternateLangLink.astro b/src/components/AlternateLangLink/AlternateLangLink.astro new file mode 100644 index 0000000..9481056 --- /dev/null +++ b/src/components/AlternateLangLink/AlternateLangLink.astro @@ -0,0 +1,30 @@ +--- +/** + * This components is used in article layout to display links in alternative lanugages. + */ +import { DEFAULT_LANGUAGE } from "@root/config"; +import { getLanguageFromURL } from "@root/utils"; + +export interface Props extends astroHTML.JSX.AnchorHTMLAttributes { + lang: LanguageKeys; +} + +const { pathname } = Astro.url; +const siteLang = getLanguageFromURL(pathname); +const { lang, ...attrs } = Astro.props as Props; +let href: string; +if (lang === DEFAULT_LANGUAGE) { + href = `/${pathname.split("/").slice(2).join("/")}`; +} else { + href = `/${lang}/`; + if (siteLang !== DEFAULT_LANGUAGE) { + href += `${pathname.split("/").slice(2).join("/")}`; + } else { + href += `${pathname.split("/").slice(1).join("/")}`; + } +} +--- + + + + diff --git a/src/components/AlternateLangLink/index.ts b/src/components/AlternateLangLink/index.ts new file mode 100644 index 0000000..49f0896 --- /dev/null +++ b/src/components/AlternateLangLink/index.ts @@ -0,0 +1 @@ +export { default } from "./AlternateLangLink.astro"; diff --git a/src/components/ArticleItem/ArticleItem.tsx b/src/components/ArticleItem/ArticleItem.tsx index 0c0e074..4051a13 100644 --- a/src/components/ArticleItem/ArticleItem.tsx +++ b/src/components/ArticleItem/ArticleItem.tsx @@ -11,7 +11,7 @@ export type ArticleItemProps = { export const ArticleItem: Component = (props) => { const isNonDefaultLanguage = props.data.lang && props.data.lang !== props.lang; - const hrefLangPrefix = props.data.lang && props.data.lang !== DEFAULT_LANGUAGE ? "/en" : ""; + const hrefLangPrefix = props.data.lang && props.data.lang !== DEFAULT_LANGUAGE ? `/${props.data.lang}` : ""; return (