Блоги #1

Merged
rndtrash merged 64 commits from feature-blogs into master 2025-10-22 08:44:56 +03:00
4 changed files with 50 additions and 6 deletions
Showing only changes of commit 451d064dea - Show all commits

5
src/app.d.ts vendored
View file

@ -18,13 +18,18 @@ declare global {
type MdsvexResolver = () => Promise<MdsvexFile>; type MdsvexResolver = () => Promise<MdsvexFile>;
type BlogPostType = 'article' | 'update' | 'event';
interface BlogPost { interface BlogPost {
slug: string; slug: string;
type?: BlogPostType;
title: string; title: string;
thumbnail?: string; thumbnail?: string;
thumbnailAlt?: string; thumbnailAlt?: string;
date?: string; date?: string;
dateChanged?: string; dateChanged?: string;
dateEventFrom?: string;
dateEventTo?: string;
description: string; description: string;
publisher: string; publisher: string;
published?: boolean; published?: boolean;

View file

@ -7,18 +7,25 @@
</script> </script>
<script lang="ts"> <script lang="ts">
import { BLOG_POST_FRESHNESS_MILLIS } from '$lib/util/Blogs'; import {
BLOG_POST_FRESHNESS_MILLIS,
blogPostTypeToIcon,
blogPostTypeToString
} from '$lib/util/Blogs';
import DateWidget from '$lib/components/DateWidget.svelte'; import DateWidget from '$lib/components/DateWidget.svelte';
import Icon from '@iconify/svelte';
export let post: App.BlogPost; export let post: App.BlogPost;
export let size: BlogCardSize = BlogCardSize.Both; export let size: BlogCardSize = BlogCardSize.Both;
const type: App.BlogPostType = post.type ?? 'article';
const dateNow = new Date().valueOf(); const dateNow = new Date().valueOf();
const isPostNew = dateNow - new Date(post.date!).valueOf() <= BLOG_POST_FRESHNESS_MILLIS; const isPostNew = dateNow - new Date(post.date!).valueOf() <= BLOG_POST_FRESHNESS_MILLIS;
const isPostUpdated = const isPostUpdated =
post.dateChanged != null && post.dateChanged != null &&
dateNow - new Date(post.dateChanged).valueOf() <= BLOG_POST_FRESHNESS_MILLIS; dateNow - new Date(post.dateChanged).valueOf() <= BLOG_POST_FRESHNESS_MILLIS;
const isPostFresh = isPostNew || isPostUpdated; const isPostFresh = isPostNew || isPostUpdated;
// TODO: rndtrash: события и их актуальность
/** /**
* rndtrash: пришлось дублировать классы с модификатором и без, потому что Tailwind просто не понимает, * rndtrash: пришлось дублировать классы с модификатором и без, потому что Tailwind просто не понимает,
@ -59,7 +66,7 @@
> >
<div <div
class="relative w-full basis-auto overflow-hidden class="relative w-full basis-auto overflow-hidden
{shortClass('h-32')} {shortClass('h-32 md:h-48')}
{fullClass('h-auto basis-1/3', 'sm:h-auto sm:basis-1/3')}" {fullClass('h-auto basis-1/3', 'sm:h-auto sm:basis-1/3')}"
> >
{#if post.thumbnail} {#if post.thumbnail}
@ -79,7 +86,7 @@
</div> </div>
{/if} {/if}
</div> </div>
<div class="flex w-full flex-col justify-center p-4 break-words md:p-8"> <div class="flex w-full flex-col justify-center p-4 break-words">
<div class="flex flex-row flex-wrap justify-start gap-4 pb-2"> <div class="flex flex-row flex-wrap justify-start gap-4 pb-2">
<DateWidget <DateWidget
class={post.dateChanged ? shortClass('hidden', 'not-sm:hidden') : ''} class={post.dateChanged ? shortClass('hidden', 'not-sm:hidden') : ''}
@ -94,6 +101,12 @@
highlight={isPostUpdated} highlight={isPostUpdated}
/> />
{/if} {/if}
<div class="flex items-center gap-2 p-1 text-lg font-bold">
<Icon icon={blogPostTypeToIcon(type)} width={28} height={28} />
<span>
{blogPostTypeToString(type)}
</span>
</div>
</div> </div>
<h2 class="text-3xl font-bold">{post.title}</h2> <h2 class="text-3xl font-bold">{post.title}</h2>

View file

@ -1,5 +1,3 @@
import path from 'path';
export const THUMBNAIL_DEFAULT = "https://teasanctuary.ru/common/background-day.webp"; export const THUMBNAIL_DEFAULT = "https://teasanctuary.ru/common/background-day.webp";
export const BLOG_POST_FRESHNESS_MILLIS = 3 * 24 * 60 * 60 * 1000; // 3 дня export const BLOG_POST_FRESHNESS_MILLIS = 3 * 24 * 60 * 60 * 1000; // 3 дня
@ -61,3 +59,23 @@ export function resolveBlogPath(slug?: string, src?: string) {
? src ? src
: `/blog/${slug}/${src}`; : `/blog/${slug}/${src}`;
} }
const bptToString: Record<App.BlogPostType, string> = {
'article': 'Заметка',
'event': 'Событие',
'update': 'Обновление'
};
const bptToIcon: Record<App.BlogPostType, string> = {
'article': 'material-symbols:article',
'event': 'material-symbols:event',
'update': 'material-symbols:autorenew'
};
export function blogPostTypeToString(type: App.BlogPostType): string {
return bptToString[type] ?? bptToString['article'];
}
export function blogPostTypeToIcon(type: App.BlogPostType): string {
return bptToIcon[type] ?? bptToIcon['article'];
}

View file

@ -4,6 +4,7 @@
import InfoBlock from '$src/lib/components/InfoBlock.svelte'; import InfoBlock from '$src/lib/components/InfoBlock.svelte';
import Icon from '@iconify/svelte'; import Icon from '@iconify/svelte';
import type { PageData } from './$types'; import type { PageData } from './$types';
import { blogPostTypeToIcon, blogPostTypeToString } from '$src/lib/util/Blogs';
export let data: PageData; export let data: PageData;
@ -14,6 +15,7 @@
: typeof data.blogPost.authors === 'string' : typeof data.blogPost.authors === 'string'
? [data.blogPost.authors] ? [data.blogPost.authors]
: data.blogPost.authors; : data.blogPost.authors;
const type: App.BlogPostType = data.blogPost.type ?? 'article';
</script> </script>
<base target="_blank" /> <base target="_blank" />
@ -44,6 +46,12 @@
{#if data.blogPost.dateChanged} {#if data.blogPost.dateChanged}
<DateWidget dateString={data.blogPost.dateChanged} type="updated" /> <DateWidget dateString={data.blogPost.dateChanged} type="updated" />
{/if} {/if}
<div class="flex items-center gap-2 p-1 text-lg font-bold">
<Icon icon={blogPostTypeToIcon(type)} width={28} height={28} />
<span>
{blogPostTypeToString(type)}
</span>
</div>
{#each authors as author} {#each authors as author}
<!-- TODO: rndtrash: из-за 404 не даёт собрать сайт. href="/team/{author}" --> <!-- TODO: rndtrash: из-за 404 не даёт собрать сайт. href="/team/{author}" -->
<a class="flex items-center gap-2 p-1 text-lg font-bold" href="#"> <a class="flex items-center gap-2 p-1 text-lg font-bold" href="#">