Add astro layouts
This commit is contained in:
34
src/components/ArticleList.astro
Normal file
34
src/components/ArticleList.astro
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
---
|
||||||
|
interface Article {
|
||||||
|
slug: string;
|
||||||
|
date: Date;
|
||||||
|
title: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
articles: Article[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const { articles } = Astro.props;
|
||||||
|
|
||||||
|
const sorted = [...articles].sort((a, b) => b.date.getTime() - a.date.getTime());
|
||||||
|
|
||||||
|
const byYear = new Map<number, Article[]>();
|
||||||
|
for (const article of sorted) {
|
||||||
|
const year = article.date.getFullYear();
|
||||||
|
if (!byYear.has(year)) {
|
||||||
|
byYear.set(year, []);
|
||||||
|
}
|
||||||
|
byYear.get(year)!.push(article);
|
||||||
|
}
|
||||||
|
---
|
||||||
|
{[...byYear.entries()].map(([year, items]) => (
|
||||||
|
<div>
|
||||||
|
<h2 class="font-bold">{year}</h2>
|
||||||
|
{items.map((article) => (
|
||||||
|
<h3>
|
||||||
|
<a href={`/articles/${article.slug}/`}>{article.title}</a>
|
||||||
|
</h3>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
9
src/components/Navigation.astro
Normal file
9
src/components/Navigation.astro
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
---
|
||||||
|
<nav class="my-4">
|
||||||
|
<ul class="flex gap-4 list-none p-0 m-0">
|
||||||
|
<li><a href="/">Главная</a></li>
|
||||||
|
<li><a href="/articles/">Блог</a></li>
|
||||||
|
<li><a href="/gallery/">Галерея</a></li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
29
src/components/YandexMetrika.astro
Normal file
29
src/components/YandexMetrika.astro
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
---
|
||||||
|
---
|
||||||
|
<script is:inline>
|
||||||
|
(function (d, w, c) {
|
||||||
|
(w[c] = w[c] || []).push(function() {
|
||||||
|
try {
|
||||||
|
w.yaCounter41913764 = new Ya.Metrika({
|
||||||
|
id: 41913764,
|
||||||
|
clickmap: true,
|
||||||
|
trackLinks: true,
|
||||||
|
accurateTrackBounce: true,
|
||||||
|
trackHash: true
|
||||||
|
});
|
||||||
|
} catch(e) { }
|
||||||
|
});
|
||||||
|
|
||||||
|
var n = d.getElementsByTagName("script")[0],
|
||||||
|
s = d.createElement("script"),
|
||||||
|
f = function () { n.parentNode.insertBefore(s, n); };
|
||||||
|
s.type = "text/javascript";
|
||||||
|
s.async = true;
|
||||||
|
s.src = "https://cdn.jsdelivr.net/npm/yandex-metrica-watch/watch.js";
|
||||||
|
|
||||||
|
if (w.opera == "[object Opera]") {
|
||||||
|
d.addEventListener("DOMContentLoaded", f, false);
|
||||||
|
} else { f(); }
|
||||||
|
})(document, window, "yandex_metrika_callbacks");
|
||||||
|
</script>
|
||||||
|
<noscript><div><img src="https://mc.yandex.ru/watch/41913764" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
|
||||||
25
src/layouts/ArticleLayout.astro
Normal file
25
src/layouts/ArticleLayout.astro
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
---
|
||||||
|
import InternalLayout from './InternalLayout.astro';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
title: string;
|
||||||
|
description?: string;
|
||||||
|
keywords?: string[];
|
||||||
|
date: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { title, description, keywords, date } = Astro.props;
|
||||||
|
|
||||||
|
const formattedDate = date.toLocaleDateString('ru-RU', {
|
||||||
|
day: '2-digit',
|
||||||
|
month: '2-digit',
|
||||||
|
year: 'numeric',
|
||||||
|
});
|
||||||
|
---
|
||||||
|
<InternalLayout title={title} description={description} keywords={keywords}>
|
||||||
|
<h1 class="text-4xl font-bold mt-3 mb-4">{title}</h1>
|
||||||
|
<slot />
|
||||||
|
<div class="border-t border-rule mt-8 pt-4">
|
||||||
|
<p>{formattedDate}, <a href="mailto:anton@vakhrushev.me">anton@vakhrushev.me</a></p>
|
||||||
|
</div>
|
||||||
|
</InternalLayout>
|
||||||
39
src/layouts/BaseLayout.astro
Normal file
39
src/layouts/BaseLayout.astro
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
---
|
||||||
|
import '../styles/global.css';
|
||||||
|
import YandexMetrika from '../components/YandexMetrika.astro';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
title?: string;
|
||||||
|
description?: string;
|
||||||
|
keywords?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const siteTitle = 'Антон Вахрушев';
|
||||||
|
const siteUrl = Astro.site?.origin ?? 'https://vakhrushev.me';
|
||||||
|
|
||||||
|
const { title, description, keywords } = Astro.props;
|
||||||
|
const pageTitle = title ? `${title} - ${siteTitle}` : siteTitle;
|
||||||
|
const pageDescription = description ?? title ?? '';
|
||||||
|
const pageUrl = `${siteUrl}${Astro.url.pathname}`;
|
||||||
|
---
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ru">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>{pageTitle}</title>
|
||||||
|
{pageDescription && <meta name="description" content={pageDescription} />}
|
||||||
|
{keywords && keywords.length > 0 && <meta name="keywords" content={keywords.join(',')} />}
|
||||||
|
<meta name="yandex-verification" content="eb6443fccb57d7d2" />
|
||||||
|
<meta property="og:site_name" content={siteTitle} />
|
||||||
|
<meta property="og:title" content={title ?? siteTitle} />
|
||||||
|
<meta property="og:description" content={pageDescription} />
|
||||||
|
<meta property="og:url" content={pageUrl} />
|
||||||
|
<meta property="og:locale" content="ru_RU" />
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=PT+Serif:wght@400;700&family=Source+Code+Pro:wght@400&display=swap&subset=cyrillic" rel="stylesheet" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<slot />
|
||||||
|
<YandexMetrika />
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
20
src/layouts/InternalLayout.astro
Normal file
20
src/layouts/InternalLayout.astro
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
import BaseLayout from './BaseLayout.astro';
|
||||||
|
import Navigation from '../components/Navigation.astro';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
title?: string;
|
||||||
|
description?: string;
|
||||||
|
keywords?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const { title, description, keywords } = Astro.props;
|
||||||
|
---
|
||||||
|
<BaseLayout title={title} description={description} keywords={keywords}>
|
||||||
|
<div class="max-w-content mx-auto px-3 sm:px-0">
|
||||||
|
<Navigation />
|
||||||
|
<main class="mb-12">
|
||||||
|
<slot />
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
</BaseLayout>
|
||||||
@@ -1,13 +1,25 @@
|
|||||||
---
|
---
|
||||||
|
import BaseLayout from '../layouts/BaseLayout.astro';
|
||||||
---
|
---
|
||||||
<html lang="ru">
|
<BaseLayout description="Личный сайт Антона Вахрушева">
|
||||||
<head>
|
<main class="max-w-content mx-auto px-3 sm:px-0">
|
||||||
<meta charset="utf-8" />
|
<h1 class="text-4xl font-bold mt-3 mb-4">Антон Вахрушев</h1>
|
||||||
<title>Антон Вахрушев</title>
|
<p>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
Я веб-программист.
|
||||||
</head>
|
Работаю в <a href="https://playkot.com/" target="_blank">Playkot</a>.
|
||||||
<body>
|
Пишу на PHP.
|
||||||
<h1>Антон Вахрушев</h1>
|
Разбираюсь в back-end, экспериментирую с front-end, интересуюсь функциональным программированием.
|
||||||
<p>Сайт в процессе обновления.</p>
|
</p>
|
||||||
</body>
|
|
||||||
</html>
|
<div class="border-t border-rule my-8"></div>
|
||||||
|
|
||||||
|
<ul class="list-none p-0 m-0">
|
||||||
|
<li>
|
||||||
|
<a href="mailto:anton@vakhrushev.me">anton@vakhrushev.me</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="https://git.vakhrushev.me" target="_blank">Код на Гитхабе</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</main>
|
||||||
|
</BaseLayout>
|
||||||
|
|||||||
@@ -8,5 +8,31 @@
|
|||||||
--color-link: #0366d6;
|
--color-link: #0366d6;
|
||||||
--color-rule: #e6e6e6;
|
--color-rule: #e6e6e6;
|
||||||
|
|
||||||
--breakpoint-content: 740px;
|
--width-content: 740px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@layer base {
|
||||||
|
html {
|
||||||
|
font-size: 20px;
|
||||||
|
|
||||||
|
@media (max-width: theme(--width-content)) {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
@apply font-serif text-text;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
@apply text-link no-underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover, a:focus, a:active {
|
||||||
|
@apply underline;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user