+
+
diff --git a/src/constants.ts b/src/constants.ts
index 4e46401..1cf32ee 100644
--- a/src/constants.ts
+++ b/src/constants.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 SUPPORTED_LANGUAGES: SupportedLanguages = ["ru", "en"];
diff --git a/src/content/blog/ispolzovanie-webserial-api-dlya-obshcheniya-s-mikrokontrollerom.md b/src/content/blog/ispolzovanie-webserial-api-dlya-obshcheniya-s-mikrokontrollerom.md
index 7003038..94ece3e 100644
--- a/src/content/blog/ispolzovanie-webserial-api-dlya-obshcheniya-s-mikrokontrollerom.md
+++ b/src/content/blog/ispolzovanie-webserial-api-dlya-obshcheniya-s-mikrokontrollerom.md
@@ -1,5 +1,6 @@
---
coverImage: /media/serial-port.jpg
+draft: false
author: Sergey Yarkov
title: Использование WebSerial API для общения с микроконтроллером
description: Речь пойдет о том, что такое WebSerial API, как его можно
@@ -10,9 +11,10 @@ tags:
- AVR
- WebSerial API
- Tutorial
-pubDate: 2022-11-04
-draft: false
+pubDate: 2022-11-04T21:00:00.000Z
+updatedDate: 2023-02-13T16:34:23.326Z
---
+
# Что вы узнаете
По итогу вы узнаете, как отправлять и принимать данные от устройства с последовательным портом в браузере, разработаете демонстрационное веб-приложение, которое отправляет команды в микроконтроллер с последовательным портом и напишите прошивку для микроконтроллера [AVR128DA48](http://ww1.microchip.com/downloads/en/DeviceDoc/40002183A.pdf) для обработки этих команд. Готовый вариант проекта можно посмотреть [здесь](https://web-serial-example.netlify.app/), исходники загружены в [репозиторий](https://github.com/sergeyyarkov/avr128da48_web-serial-example) на GitHub.
@@ -47,17 +49,17 @@ WebSerial API - это браузерный API, который предоста
UART передает данные последовательно по одному биту в одном из трех режимов:
-* односторонний режим - данные отправляются только в одном направлении, от передатчика к приемнику
-* полудуплексный режим - устройства могут передавать и принимать данные по очереди
-* полнодуплексный режим - устройства могут передавать и принимать данные одновременно
+- односторонний режим - данные отправляются только в одном направлении, от передатчика к приемнику
+- полудуплексный режим - устройства могут передавать и принимать данные по очереди
+- полнодуплексный режим - устройства могут передавать и принимать данные одновременно
Так как в этом проекте предполагается использование асинхронной версии UART, то соответственно необходимо устанавливать **одинаковую** скорость передачи битов в секунду (`baud rate`, `bps`) на двух устройствах. Наиболее распространенные скорости являются: **4800, 9600, 19.2 К, 57.6К и 115.2К.**
Данные передаются в виде так называемых `пакетов`, где каждый пакет содержит в себе:
-* стартовый и стоповый биты - стартовый бит сигнализирует о поступлении битов данных, стоповый соответственно о конце данных.
-* биты данных - пользовательские данные, которые поступают сразу после стартового бита, может содержаться от 5 до 8 битов.
-* бит четности - необязательный бит, который идет после битов данных и перед стоповым битом и используется для обнаружения ошибок.
+- стартовый и стоповый биты - стартовый бит сигнализирует о поступлении битов данных, стоповый соответственно о конце данных.
+- биты данных - пользовательские данные, которые поступают сразу после стартового бита, может содержаться от 5 до 8 битов.
+- бит четности - необязательный бит, который идет после битов данных и перед стоповым битом и используется для обнаружения ошибок.
@@ -82,7 +84,7 @@ UART передает данные последовательно по одно
Как я упомянул ранее, прошивка будет написана для микроконтроллера AVR128DA48. На самом деле неважно какой микроконтроллер вы используете, вам достаточно нужно уметь отправлять и принимать данные используя UART периферию вашего микроконтроллера.
-Суть программы будет очень проста: необходимо написать некий ***обработчик команд*** который будет принимать на вход строку (например `led_toggle`) и вызывать необходимую функцию, которая будет выполнять какое-то действие, в данном случае переключать светодиод.
+Суть программы будет очень проста: необходимо написать некий **_обработчик команд_** который будет принимать на вход строку (например `led_toggle`) и вызывать необходимую функцию, которая будет выполнять какое-то действие, в данном случае переключать светодиод.
Постановка задачи ясна, теперь рассмотрим реализацию данной программы. Я буду использовать среду разработки MPLAB X IDE и язык C для написания прошивки.
@@ -102,10 +104,10 @@ UART передает данные последовательно по одно
#endif /* CONSTANTS_H */
```
-* `F_CPU` - тактовая частота микроконтроллера
-* `BAUD_RATE` - скорость передачи данных UART
-* `BUFFER_SIZE` - размер буфера, куда будем складывать поступающие данные
-* `EOT` - End-of-Transmission, ASCII символ конца передачи данных
+- `F_CPU` - тактовая частота микроконтроллера
+- `BAUD_RATE` - скорость передачи данных UART
+- `BUFFER_SIZE` - размер буфера, куда будем складывать поступающие данные
+- `EOT` - End-of-Transmission, ASCII символ конца передачи данных
## Инициализация USART
@@ -155,11 +157,11 @@ void USART1_Initialize(void) {
Для полнодуплексного режима инициализация асинхронной версии USART происходит следующим образом:
-* Конфигурация скорости передачи данных путем записывания значения в регистр `USARTn.BAUD`
-* Конфигурация размера `фрейма`, в нашем случае это 8 бит.
-* Конфигурация пина `TX` на выход и пина `RX` на вход.
-* Включение прерывания на то, когда закончился прием данных (когда пришел один пакет).
-* Включение приемника и передатчика.
+- Конфигурация скорости передачи данных путем записывания значения в регистр `USARTn.BAUD`
+- Конфигурация размера `фрейма`, в нашем случае это 8 бит.
+- Конфигурация пина `TX` на выход и пина `RX` на вход.
+- Включение прерывания на то, когда закончился прием данных (когда пришел один пакет).
+- Включение приемника и передатчика.
Теперь, рассмотрим функции отправки данных:
@@ -211,9 +213,9 @@ void command_list(void);
Для решения этой задачи я предлагаю создавать массив структур, где в каждой структуре будет содержаться указатель на функцию которую нам нужно выполнить, и название самой команды.
-* `command_define` будет создавать новую структуру в массиве.
-* `command_process` будет вызывать соответствующую функцию по имени команды.
-* `command_list` будет отправлять по UART информацию о существующих командах.
+- `command_define` будет создавать новую структуру в массиве.
+- `command_process` будет вызывать соответствующую функцию по имени команды.
+- `command_list` будет отправлять по UART информацию о существующих командах.
Реализовать задуманное можно следующим образом создав файл `command.c`:
@@ -367,9 +369,9 @@ void hello_world(void) {
С помощью функции `command_define` мы можем определить, по какой переданной команде по USART запускать функцию:
-* `led_toggle` будет переключать светодиод.
-* `hello_world` выводить сообщение “Hello world”.
-* `command_list` будет показывать список имеющихся команд.
+- `led_toggle` будет переключать светодиод.
+- `hello_world` выводить сообщение “Hello world”.
+- `command_list` будет показывать список имеющихся команд.
## Демонстрация работы
@@ -377,10 +379,10 @@ void hello_world(void) {
Выберете ваше устройство из списка (в моем случае это `/dev/ttyACM1`) и установите следующие настройки:
-* Скорость: **9600** бод
-* Количество битов: **8**
-* Четность: **None**
-* Стоповые биты: **1**
+- Скорость: **9600** бод
+- Количество битов: **8**
+- Четность: **None**
+- Стоповые биты: **1**
{
# Полезные материалы
-* [Статус поддержки браузеров Can I use](https://caniuse.com/web-serial)
-* [Документация к WebSerial API](https://wicg.github.io/serial/)
-* [Подробное руководство по Stream API](https://web.dev/streams/)
-* [Список USB идентификаторов](https://devicehunt.com/all-usb-vendors)
-* [Доступ к различным устройствам из браузера](https://web.dev/devices-introduction/)
\ No newline at end of file
+- [Статус поддержки браузеров Can I use](https://caniuse.com/web-serial)
+- [Документация к WebSerial API](https://wicg.github.io/serial/)
+- [Подробное руководство по Stream API](https://web.dev/streams/)
+- [Список USB идентификаторов](https://devicehunt.com/all-usb-vendors)
+- [Доступ к различным устройствам из браузера](https://web.dev/devices-introduction/)
diff --git a/src/content/config.ts b/src/content/config.ts
index f2b0405..22cd6ea 100644
--- a/src/content/config.ts
+++ b/src/content/config.ts
@@ -13,8 +13,10 @@ const blog = defineCollection({
.transform((val) => new Date(val)),
updatedDate: z
.string()
+ .or(z.date())
.optional()
.transform((str) => (str ? new Date(str) : undefined)),
+ draft: z.boolean(),
}),
});
@@ -31,4 +33,17 @@ const authors = defineCollection({
}),
});
-export const collections = { blog, tags, authors };
+const projects = defineCollection({
+ schema: z.object({
+ icon: z.string(),
+ title: z.string(),
+ year: z.number(),
+ description: z.string(),
+ sourceUrl: z.string(),
+ demoUrl: z.string().nullable().optional(),
+ articleUrl: z.string().nullable().optional(),
+ draft: z.boolean(),
+ }),
+});
+
+export const collections = { blog, tags, authors, projects };
diff --git a/src/content/projects/en/devthread.md b/src/content/projects/en/devthread.md
new file mode 100644
index 0000000..cfcc406
--- /dev/null
+++ b/src/content/projects/en/devthread.md
@@ -0,0 +1,11 @@
+---
+icon: triangle_filled
+draft: false
+title: devthread
+year: 2021
+description: Static website for publishing various articles, developed with
+ Gatsby.js and NetlifyCMS
+sourceUrl: https://github.com/sergeyyarkov/devthread.ru
+demoUrl: https://devthread.yarkov.tech
+articleUrl: null
+---
diff --git a/src/content/projects/en/digital-store.md b/src/content/projects/en/digital-store.md
new file mode 100644
index 0000000..5c927d3
--- /dev/null
+++ b/src/content/projects/en/digital-store.md
@@ -0,0 +1,10 @@
+---
+icon: round-shop-two
+draft: false
+title: digital-store
+year: 2019
+description: Customizable online store with control panel for selling digital goods
+sourceUrl: https://github.com/sergeyyarkov/digital-store/tree/digital-store-docker
+demoUrl: https://digital-store.herokuapp.com
+articleUrl: null
+---
diff --git a/src/content/projects/en/educt.md b/src/content/projects/en/educt.md
new file mode 100644
index 0000000..5091d5c
--- /dev/null
+++ b/src/content/projects/en/educt.md
@@ -0,0 +1,10 @@
+---
+icon: round-school
+draft: false
+title: educt
+year: 2022
+description: Learning Management System (LMS) to publish your courses, lectures, lessons
+sourceUrl: https://github.com/sergeyyarkov/educt
+demoUrl: https://educt.yarkov.tech
+articleUrl: null
+---
diff --git a/src/content/projects/en/memory-led-game.md b/src/content/projects/en/memory-led-game.md
new file mode 100644
index 0000000..fe9098c
--- /dev/null
+++ b/src/content/projects/en/memory-led-game.md
@@ -0,0 +1,10 @@
+---
+icon: chip
+draft: false
+title: memory-led-game
+year: 2022
+description: Analogue of the popular game "Simon says" on the AVR microcontroller
+sourceUrl: https://github.com/sergeyyarkov/attiny24a_memory-led-game
+demoUrl: null
+articleUrl: null
+---
diff --git a/src/content/projects/en/node-docker-example.md b/src/content/projects/en/node-docker-example.md
new file mode 100644
index 0000000..a7e54cf
--- /dev/null
+++ b/src/content/projects/en/node-docker-example.md
@@ -0,0 +1,10 @@
+---
+icon: nodejs
+draft: false
+title: node-docker-example
+year: 2022
+description: An example of using Docker to deploy a Node.js application
+sourceUrl: https://github.com/sergeyyarkov/node-docker-example
+demoUrl: https://node-docker-example.onrender.com
+articleUrl: null
+---
diff --git a/src/content/projects/en/react-chat-app.md b/src/content/projects/en/react-chat-app.md
new file mode 100644
index 0000000..97527b8
--- /dev/null
+++ b/src/content/projects/en/react-chat-app.md
@@ -0,0 +1,10 @@
+---
+icon: chat
+draft: false
+title: react-chat-app
+year: 2021
+description: Client-server web chat application developed with Node.js and Socket.io
+sourceUrl: https://github.com/sergeyyarkov/react-chat-app
+demoUrl: null
+articleUrl: null
+---
diff --git a/src/content/projects/en/web-serial-example.md b/src/content/projects/en/web-serial-example.md
new file mode 100644
index 0000000..1c9a973
--- /dev/null
+++ b/src/content/projects/en/web-serial-example.md
@@ -0,0 +1,11 @@
+---
+icon: serial
+draft: false
+title: web-serial-example
+year: 2022
+description: An example of using the Web Serial API to interact with the
+ microcontroller through a browser
+sourceUrl: https://github.com/sergeyyarkov/avr128da48_web-serial-example
+demoUrl: https://web-serial-example.netlify.app
+articleUrl: null
+---
diff --git a/src/content/projects/en/yarkov-tech.md b/src/content/projects/en/yarkov-tech.md
new file mode 100644
index 0000000..5f9ab7c
--- /dev/null
+++ b/src/content/projects/en/yarkov-tech.md
@@ -0,0 +1,11 @@
+---
+icon: book
+draft: false
+title: yarkov.tech
+year: 2023
+description: My personal website where you can find information about me and a
+ list of various articles and tutorials...
+sourceUrl: https://github.com/sergeyyarkov/yarkov.tech
+demoUrl: https://yarkov.tech
+articleUrl: null
+---
diff --git a/src/content/projects/ru/devthread.md b/src/content/projects/ru/devthread.md
new file mode 100644
index 0000000..4874eec
--- /dev/null
+++ b/src/content/projects/ru/devthread.md
@@ -0,0 +1,10 @@
+---
+icon: triangle_filled
+draft: false
+title: devthread
+year: 2021
+description: Статический веб-сайт для публикации различных статей, разработанный
+ при помощи Gatsby.js и NetlifyCMS
+sourceUrl: https://github.com/sergeyyarkov/devthread.ru
+demoUrl: https://devthread.yarkov.tech
+---
diff --git a/src/content/projects/ru/digital-store.md b/src/content/projects/ru/digital-store.md
new file mode 100644
index 0000000..3b9f2a2
--- /dev/null
+++ b/src/content/projects/ru/digital-store.md
@@ -0,0 +1,10 @@
+---
+icon: round-shop-two
+draft: false
+title: digital-store
+year: 2019
+description: Настраиваемый интернет-магазин с панелью управления для продажи
+ цифровых товаров
+sourceUrl: https://github.com/sergeyyarkov/digital-store/tree/digital-store-docker
+demoUrl: https://digital-store.herokuapp.com
+---
diff --git a/src/content/projects/ru/educt.md b/src/content/projects/ru/educt.md
new file mode 100644
index 0000000..f2e3562
--- /dev/null
+++ b/src/content/projects/ru/educt.md
@@ -0,0 +1,9 @@
+---
+icon: round-school
+draft: false
+title: educt
+year: 2022
+description: Система управления обучением (LMS) для публикации ваших курсов, лекций, уроков
+sourceUrl: https://github.com/sergeyyarkov/educt
+demoUrl: https://educt.yarkov.tech
+---
diff --git a/src/content/projects/ru/memory-led-game.md b/src/content/projects/ru/memory-led-game.md
new file mode 100644
index 0000000..6ef27af
--- /dev/null
+++ b/src/content/projects/ru/memory-led-game.md
@@ -0,0 +1,8 @@
+---
+icon: chip
+draft: false
+title: memory-led-game
+year: 2022
+description: Аналог популярной игры "Саймон говорит" на AVR микроконтроллере
+sourceUrl: https://github.com/sergeyyarkov/attiny24a_memory-led-game
+---
diff --git a/src/content/projects/ru/node-docker-example.md b/src/content/projects/ru/node-docker-example.md
new file mode 100644
index 0000000..1a1e68e
--- /dev/null
+++ b/src/content/projects/ru/node-docker-example.md
@@ -0,0 +1,9 @@
+---
+icon: nodejs
+draft: false
+title: node-docker-example
+year: 2022
+description: Пример использования Docker для развертывания Node.js приложения
+sourceUrl: https://github.com/sergeyyarkov/node-docker-example
+demoUrl: https://node-docker-example.onrender.com
+---
diff --git a/src/content/projects/ru/react-chat-app.md b/src/content/projects/ru/react-chat-app.md
new file mode 100644
index 0000000..be4524f
--- /dev/null
+++ b/src/content/projects/ru/react-chat-app.md
@@ -0,0 +1,9 @@
+---
+icon: chat
+draft: false
+title: react-chat-app
+year: 2021
+description: Клиент-серверное веб приложение чата разработанное при помощи
+ Node.js и Socket.io
+sourceUrl: https://github.com/sergeyyarkov/react-chat-app
+---
diff --git a/src/content/projects/ru/web-serial-example.md b/src/content/projects/ru/web-serial-example.md
new file mode 100644
index 0000000..04e68d3
--- /dev/null
+++ b/src/content/projects/ru/web-serial-example.md
@@ -0,0 +1,11 @@
+---
+icon: serial
+draft: false
+title: web-serial-example
+year: 2022
+description: Пример использования Web Serial API для взаимодействия с
+ микроконтроллером через браузер.
+sourceUrl: https://github.com/sergeyyarkov/avr128da48_web-serial-example
+demoUrl: https://web-serial-example.netlify.app
+articleUrl: https://yarkov.tech/blog/2022-11-04/ispolzovanie-webserial-api-dlya-obshcheniya-s-mikrokontrollerom/
+---
diff --git a/src/content/projects/ru/yarkov-tech.md b/src/content/projects/ru/yarkov-tech.md
new file mode 100644
index 0000000..6b36f25
--- /dev/null
+++ b/src/content/projects/ru/yarkov-tech.md
@@ -0,0 +1,10 @@
+---
+icon: book
+draft: false
+title: yarkov.tech
+year: 2023
+description: Мой персональный веб-сайт где находятся информация обо мне и список
+ различных статей и туториалов...
+sourceUrl: https://github.com/sergeyyarkov/yarkov.tech
+demoUrl: https://yarkov.tech
+---
diff --git a/src/content/site-settings.yml b/src/content/site-settings.yml
new file mode 100644
index 0000000..5816334
--- /dev/null
+++ b/src/content/site-settings.yml
@@ -0,0 +1,3 @@
+globalTitle: yarkov.tech
+articles:
+ recentLimit: 5
diff --git a/src/i18n/languages.ts b/src/i18n/languages.ts
index 3068727..ceb7191 100644
--- a/src/i18n/languages.ts
+++ b/src/i18n/languages.ts
@@ -1,5 +1,4 @@
export default {
ru: "Русский",
en: "English",
- de: "Deutsch",
};
diff --git a/src/i18n/utils.ts b/src/i18n/utils.ts
index 0f726a9..eeff31f 100644
--- a/src/i18n/utils.ts
+++ b/src/i18n/utils.ts
@@ -1,6 +1,5 @@
-import type { AstroGlobal, MDXInstance } from "astro";
import languages from "./languages";
-import { DEFAULT_LANGUAGE } from "@root/constants";
+import { DEFAULT_LANGUAGE, SUPPORTED_LANGUAGES } from "@root/constants";
function transformExports(modules: Record) {
const translations: Record = {};
@@ -11,6 +10,12 @@ function transformExports(modules: Record) {
return translations;
}
+export function getLanguageKeys(): Array {
+ return Object.keys(languages).filter((lang) =>
+ SUPPORTED_LANGUAGES.includes(lang as LanguageKeys)
+ );
+}
+
export const getLanguageFromURL = (pathname: string): LanguageKeys => {
const lang = pathname.split("/")[1] as LanguageKeys;
if (Object.hasOwn(languages, lang)) return lang;
diff --git a/src/layouts/article.astro b/src/layouts/article.astro
index d5728f7..67d5fd5 100644
--- a/src/layouts/article.astro
+++ b/src/layouts/article.astro
@@ -1,38 +1,42 @@
---
-import type { Props as BaseHeadProps } from "@root/components/BaseHead.astro";
+import type { CollectionEntry } from "astro:content";
+import { DEFAULT_LANGUAGE, SITE_METADATA } from "@root/constants";
import BaseHead from "@components/BaseHead.astro";
import BaseLayout from "@components/BaseLayout.astro";
import ArticleContent from "@components/ArticleContent/ArticleContent.astro";
import ArticlePost from "@components/ArticlePost/ArticlePost.astro";
-import { SITE_METADATA } from "@root/constants";
-import type { CollectionEntry } from "astro:content";
+import OpenGraph from "@components/OpenGraph.astro";
export interface Props {
lang?: string | undefined;
- content: CollectionEntry<"blog">;
+ article: CollectionEntry<"blog">;
}
-const { lang = "ru", content } = Astro.props as Props;
+
+const canonicalUrl = new URL(Astro.url.pathname, Astro.site);
+const { lang = DEFAULT_LANGUAGE, article } = Astro.props as Props;
+const {
+ data: { title, description, coverImage },
+} = article;
---
-
-
-
-
-
-
-
+
+
-
+
diff --git a/src/layouts/default.astro b/src/layouts/default.astro
index a976a71..3024641 100644
--- a/src/layouts/default.astro
+++ b/src/layouts/default.astro
@@ -1,6 +1,6 @@
---
import type { Props as BaseHeadProps } from "@components/BaseHead.astro";
-import { SITE_METADATA } from "@root/constants";
+import { DEFAULT_LANGUAGE, SITE_METADATA } from "@root/constants";
import BaseHead from "@components/BaseHead.astro";
import BaseLayout from "@components/BaseLayout.astro";
@@ -10,11 +10,14 @@ export interface Props extends BaseHeadProps {
canonicalUrl?: string | undefined;
}
-const { title, description, lang = "ru", noIndex = false } = Astro.props as Props;
+const { title, description, lang = DEFAULT_LANGUAGE, noIndex = false } = Astro.props as Props;
---
-
+
{noIndex && }
diff --git a/src/pages/404.astro b/src/pages/404.astro
new file mode 100644
index 0000000..e5393c6
--- /dev/null
+++ b/src/pages/404.astro
@@ -0,0 +1,5 @@
+---
+import NotFound from "@templates/NotFound.astro";
+---
+
+
diff --git a/src/pages/[...slug].astro b/src/pages/[...slug].astro
new file mode 100644
index 0000000..62dec71
--- /dev/null
+++ b/src/pages/[...slug].astro
@@ -0,0 +1,22 @@
+---
+import { CollectionEntry, getCollection } from "astro:content";
+import ArticleLayout from "@root/layouts/article.astro";
+
+export async function getStaticPaths() {
+ const articles = await getCollection("blog");
+ return articles
+ .filter((a) => !a.data.draft)
+ .map((article) => ({
+ params: { slug: `articles/${article.slug}` },
+ props: { article },
+ }));
+}
+
+type Props = { article: CollectionEntry<"blog"> };
+
+const { Content } = await Astro.props.article.render();
+---
+
+
+
+
diff --git a/src/pages/[lang]/about.astro b/src/pages/[lang]/about.astro
new file mode 100644
index 0000000..ea752f0
--- /dev/null
+++ b/src/pages/[lang]/about.astro
@@ -0,0 +1,13 @@
+---
+import { getLanguageKeys } from "@i18n/utils";
+import { DEFAULT_LANGUAGE } from "@root/constants";
+import About from "@templates/About.astro";
+
+export function getStaticPaths() {
+ return getLanguageKeys()
+ .filter((lang) => lang !== DEFAULT_LANGUAGE)
+ .map((lang) => ({ params: { lang } }));
+}
+---
+
+
diff --git a/src/pages/[lang]/articles.astro b/src/pages/[lang]/articles.astro
new file mode 100644
index 0000000..727d04a
--- /dev/null
+++ b/src/pages/[lang]/articles.astro
@@ -0,0 +1,13 @@
+---
+import { getLanguageKeys } from "@i18n/utils";
+import { DEFAULT_LANGUAGE } from "@root/constants";
+import Articles from "@templates/Articles.astro";
+
+export function getStaticPaths() {
+ return getLanguageKeys()
+ .filter((lang) => lang !== DEFAULT_LANGUAGE)
+ .map((lang) => ({ params: { lang } }));
+}
+---
+
+
diff --git a/src/pages/[lang]/contacts.astro b/src/pages/[lang]/contacts.astro
new file mode 100644
index 0000000..f306c2c
--- /dev/null
+++ b/src/pages/[lang]/contacts.astro
@@ -0,0 +1,13 @@
+---
+import { getLanguageKeys } from "@i18n/utils";
+import { DEFAULT_LANGUAGE } from "@root/constants";
+import Contacts from "@templates/Contacts.astro";
+
+export function getStaticPaths() {
+ return getLanguageKeys()
+ .filter((lang) => lang !== DEFAULT_LANGUAGE)
+ .map((lang) => ({ params: { lang } }));
+}
+---
+
+
diff --git a/src/pages/[lang]/index.astro b/src/pages/[lang]/index.astro
new file mode 100644
index 0000000..ac6b969
--- /dev/null
+++ b/src/pages/[lang]/index.astro
@@ -0,0 +1,13 @@
+---
+import { getLanguageKeys } from "@i18n/utils";
+import { DEFAULT_LANGUAGE } from "@root/constants";
+import Home from "@templates/Home.astro";
+
+export function getStaticPaths() {
+ return getLanguageKeys()
+ .filter((lang) => lang !== DEFAULT_LANGUAGE)
+ .map((lang) => ({ params: { lang } }));
+}
+---
+
+
diff --git a/src/pages/[lang]/projects.astro b/src/pages/[lang]/projects.astro
new file mode 100644
index 0000000..d80541a
--- /dev/null
+++ b/src/pages/[lang]/projects.astro
@@ -0,0 +1,13 @@
+---
+import { getLanguageKeys } from "@i18n/utils";
+import { DEFAULT_LANGUAGE } from "@root/constants";
+import Projects from "@templates/Projects.astro";
+
+export function getStaticPaths() {
+ return getLanguageKeys()
+ .filter((lang) => lang !== DEFAULT_LANGUAGE)
+ .map((lang) => ({ params: { lang } }));
+}
+---
+
+
diff --git a/src/pages/about.astro b/src/pages/about.astro
new file mode 100644
index 0000000..cc2f54e
--- /dev/null
+++ b/src/pages/about.astro
@@ -0,0 +1,5 @@
+---
+import About from "@templates/About.astro";
+---
+
+
diff --git a/src/pages/articles.astro b/src/pages/articles.astro
new file mode 100644
index 0000000..6c3a258
--- /dev/null
+++ b/src/pages/articles.astro
@@ -0,0 +1,5 @@
+---
+import Articles from "@templates/Articles.astro";
+---
+
+
diff --git a/src/pages/articles/[...slug].astro b/src/pages/articles/[...slug].astro
deleted file mode 100644
index 77099e2..0000000
--- a/src/pages/articles/[...slug].astro
+++ /dev/null
@@ -1,21 +0,0 @@
----
-import { CollectionEntry, getCollection } from "astro:content";
-import ArticleLayout from "@root/layouts/article.astro";
-
-export async function getStaticPaths() {
- const posts = await getCollection("blog");
- return posts.map((post) => ({
- params: { slug: post.slug },
- props: post,
- }));
-}
-
-type Props = CollectionEntry<"blog">;
-
-const post = Astro.props;
-const { Content } = await post.render();
----
-
-
-
-
diff --git a/src/pages/ping.astro b/src/pages/ping.astro
new file mode 100644
index 0000000..7aacb1d
--- /dev/null
+++ b/src/pages/ping.astro
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+ pong
+
+ pong
+
diff --git a/src/pages/projects.astro b/src/pages/projects.astro
new file mode 100644
index 0000000..bc45be5
--- /dev/null
+++ b/src/pages/projects.astro
@@ -0,0 +1,5 @@
+---
+import Projects from "@root/templates/Projects.astro";
+---
+
+
diff --git a/src/templates/About.astro b/src/templates/About.astro
new file mode 100644
index 0000000..0573bc9
--- /dev/null
+++ b/src/templates/About.astro
@@ -0,0 +1,26 @@
+---
+import PageLayout from "@layouts/default.astro";
+import { getLanguageFromURL } from "@i18n/utils";
+// import { useTranslation } from "@i18n/utils";
+// import * as API from "@root/lib/api";
+import PageHeading from "@components/PageHeading.astro";
+// import SkillsList from "@components/SkillsList";
+// import SkillsBlock from "@components/SkillsBlock";
+// import ArticleContent from "@components/ArticleContent";
+const lang = getLanguageFromURL(Astro.url.pathname);
+// const t = useTranslation(Astro);
+// const data = await API.fetchAboutMe(Astro);
+// const { skills } = SITE_METADATA;
+---
+
+
+
+
+
+
+
+
diff --git a/src/templates/Articles.astro b/src/templates/Articles.astro
new file mode 100644
index 0000000..6aa128e
--- /dev/null
+++ b/src/templates/Articles.astro
@@ -0,0 +1,39 @@
+---
+import PageLayout from "@layouts/default.astro";
+import PageHeading from "@components/PageHeading.astro";
+// import ArticlesList from "@components/ArticlesList";
+// import * as utils from "@utils/articles";
+import { getLanguageFromURL } from "@i18n/utils";
+// import { useTranslation } from "@i18n/utils";
+// import * as API from "@root/lib/api";
+// const t = useTranslation(Astro);
+// const data = API.fetchTranslatedArticles(Astro);
+// const tags = new Set(data.map((article) => article.frontmatter.tags).flat());
+const lang = getLanguageFromURL(Astro.url.pathname);
+// const articles = utils.transformArticles(data);
+const canonicalUrl = new URL(Astro.url.pathname, Astro.site);
+---
+
+
+
+
+ ...
+
+
+
diff --git a/src/templates/Home.astro b/src/templates/Home.astro
index dc6909b..053ed26 100644
--- a/src/templates/Home.astro
+++ b/src/templates/Home.astro
@@ -7,7 +7,9 @@ import SplashLink from "@root/components/Splash/SplashLink.astro";
import { getCollection } from "astro:content";
import RecentArticles from "@root/components/RecentArticles.astro";
-const articles = (await getCollection("blog")).sort((a, b) => a.data.pubDate.valueOf() - b.data.pubDate.valueOf());
+const articles = (await getCollection("blog"))
+ .filter((p) => !p.data.draft)
+ .sort((a, b) => a.data.pubDate.valueOf() - b.data.pubDate.valueOf());
---
@@ -18,8 +20,8 @@ const articles = (await getCollection("blog")).sort((a, b) => a.data.pubDate.val
Fullstack web-developer & freelancer
- Я занимаюсь разработкой веб-сайтов и веб-приложений разной сложности, а также публикую статьи и туториалы на
- разные IT темы.
+ Я занимаюсь разработкой веб-сайтов и веб-приложений разной сложности, а также публикую
+ статьи и туториалы на разные IT темы.
diff --git a/src/templates/NotFound.astro b/src/templates/NotFound.astro
new file mode 100644
index 0000000..31b8bd4
--- /dev/null
+++ b/src/templates/NotFound.astro
@@ -0,0 +1,13 @@
+---
+import PageLayout from "@layouts/default.astro";
+import { getLanguageFromURL } from "@i18n/utils";
+const lang = getLanguageFromURL(Astro.url.pathname);
+// const t = useTranslation(Astro);
+---
+
+
+
+
404
+
{"Страница не найдена"}
+
+
diff --git a/src/templates/Projects.astro b/src/templates/Projects.astro
new file mode 100644
index 0000000..8db4af7
--- /dev/null
+++ b/src/templates/Projects.astro
@@ -0,0 +1,31 @@
+---
+import PageLayout from "@layouts/default.astro";
+import ProjectsList from "@components/ProjectsList.astro";
+import ProjectItem from "@components/ProjectItem.astro";
+import PageHeading from "@components/PageHeading.astro";
+import { getLanguageFromURL } from "@i18n/utils";
+import { getCollection } from "astro:content";
+// import { useTranslation } from "@i18n/utils";
+// const t = useTranslation(Astro);
+const lang = getLanguageFromURL(Astro.url.pathname);
+const projects = (await getCollection("projects")).filter(
+ (p) => !p.data.draft && p.id.split(".")[1] === lang
+);
+---
+
+
+
+
+
+ {projects.map((project) => )}
+
+
+