add real authors

This commit is contained in:
Profile Profile
2026-01-28 12:02:55 +03:00
parent c01845bb39
commit 1b5530392f
5 changed files with 449 additions and 253 deletions

View File

@@ -0,0 +1,200 @@
---
export interface Props {
coauthors: any[];
prefix?: string;
className?: string;
}
const {
coauthors = [],
prefix = '',
className = '',
} = Astro.props;
function getAuthorUrl(coauthor: any): string {
if (coauthor?.url) return coauthor.url;
if (coauthor?.uri) return coauthor.uri;
if (coauthor?.databaseId) return `/author/${coauthor.databaseId}`;
return '#';
}
---
{coauthors.length > 0 && (
<div
class={`coauthors-inline ${className}`}
itemprop="contributor"
itemtype="https://schema.org/Person"
>
{prefix && <span class="coauthors-prefix">{prefix}</span>}
{coauthors.map((coauthor, index) => {
const authorUrl = getAuthorUrl(coauthor);
const isLast = index === coauthors.length - 1;
return (
<span class="coauthor-wrapper" key={coauthor.id || index}>
<a
href={authorUrl}
class="coauthor-name"
itemprop="name"
title={coauthor.name}
>
{coauthor.name}
</a>
{!isLast && <span class="comma">, </span>}
</span>
);
})}
</div>
)}
<style>
/* Основные стили компонента */
.coauthors-inline {
font-size: 12px;
color: rgba(255, 255, 255, 0.85);
display: flex;
flex-wrap: wrap;
align-items: baseline;
margin-top: 3px;
line-height: 1.3;
font-weight: 400;
}
/* Префикс (если используется) */
.coauthors-prefix {
font-weight: 400;
color: rgba(255, 255, 255, 0.85);
margin-right: 4px;
white-space: nowrap;
}
/* Обертка для каждого автора */
.coauthor-wrapper {
display: inline-flex;
align-items: center;
}
/* Ссылка на автора */
.coauthor-name {
color: rgba(255, 255, 255, 0.85);
text-decoration: none;
transition: all 0.2s ease;
font-weight: 400;
}
/* Ховер эффект для ссылки */
.coauthor-name:hover {
color: rgba(255, 255, 255, 1);
text-decoration: underline;
}
/* Фокус состояние для доступности */
.coauthor-name:focus {
outline: 2px solid rgba(255, 255, 255, 0.7);
outline-offset: 2px;
border-radius: 2px;
}
/* Запятая между авторами */
.comma {
color: rgba(255, 255, 255, 0.7);
margin: 0 2px;
}
/* Стили для больших карточек (post-card-large) */
.post-card-large .coauthors-inline {
font-size: 13px;
margin-top: 5px;
}
/* Адаптивные стили */
/* Планшеты */
@media (max-width: 991px) {
.coauthors-inline {
font-size: 11px;
}
}
/* Мобильные устройства */
@media (max-width: 767px) {
.coauthors-inline {
font-size: 11px;
}
}
/* Очень маленькие экраны */
@media (max-width: 480px) {
.coauthors-inline {
font-size: 10px;
}
}
/* Варианты модификаторов класса */
/* Темная тема для светлого фона */
.coauthors-inline.dark-theme {
color: rgba(0, 0, 0, 0.85);
}
.coauthors-inline.dark-theme .coauthors-prefix {
color: rgba(0, 0, 0, 0.85);
}
.coauthors-inline.dark-theme .coauthor-name {
color: rgba(0, 0, 0, 0.85);
}
.coauthors-inline.dark-theme .coauthor-name:hover {
color: rgba(0, 0, 0, 1);
}
.coauthors-inline.dark-theme .comma {
color: rgba(0, 0, 0, 0.7);
}
/* Без префикса */
.coauthors-inline.no-prefix {
gap: 0;
}
.coauthors-inline.no-prefix .coauthors-prefix {
display: none;
}
/* Компактный вариант */
.coauthors-inline.compact {
font-size: 11px;
margin-top: 2px;
line-height: 1.2;
}
/* Расширенный вариант */
.coauthors-inline.expanded {
font-size: 14px;
margin-top: 6px;
line-height: 1.4;
}
/* Вариант с жирным текстом */
.coauthors-inline.bold .coauthor-name {
font-weight: 500;
}
/* Вариант с курсивом */
.coauthors-inline.italic .coauthor-name {
font-style: italic;
}
/* Вариант с подчеркиванием при наведении */
.coauthors-inline.underline-on-hover .coauthor-name:hover {
text-decoration: underline;
}
/* Вариант без подчеркивания */
.coauthors-inline.no-underline .coauthor-name:hover {
text-decoration: none;
opacity: 0.9;
}
</style>

View File

@@ -6,19 +6,17 @@ export interface Props {
const {
items = [],
showCount = false,
showCount = false,
} = Astro.props;
// Функция для извлечения класса цвета из строки
function extractColorClass(colorString: string): string {
if (!colorString) return 'bg-blue';
// Если строка содержит "фон меню:" - извлекаем часть после двоеточия
if (colorString.includes('фон меню:')) {
const parts = colorString.split(':');
const color = parts[1]?.trim();
// Проверяем существование CSS класса
const validColors = [
'black', 'yellow', 'blue', 'green', 'red', 'orange', 'gray',
'indigo', 'purple', 'pink', 'teal', 'cyan', 'white',
@@ -30,12 +28,10 @@ function extractColorClass(colorString: string): string {
}
}
// Если строка уже содержит "bg-"
if (colorString.startsWith('bg-')) {
return colorString;
}
// Если это просто название цвета без префикса
const simpleColor = colorString.toLowerCase();
switch(simpleColor) {
case 'black': case 'yellow': case 'blue': case 'green':
@@ -47,8 +43,17 @@ function extractColorClass(colorString: string): string {
default: return 'bg-blue';
}
}
---
// Функция для получения списка имен соавторов
function getCoauthorsNames(coauthors: any[]): string {
if (!coauthors || coauthors.length === 0) return '';
return coauthors
.map((coauthor: any) => coauthor?.node?.name || coauthor?.name)
.filter(Boolean)
.join(' ');
}
---
<section class="posts-section" id="posts-section">
<h2>
@@ -61,12 +66,12 @@ function extractColorClass(colorString: string): string {
{items.map((item, index) => {
const postUrl = item.uri || `/blog/${item.databaseId}`;
const postDate = new Date(item.date);
const coauthors = item.coauthors || [];
const coauthorsNames = getCoauthorsNames(coauthors);
// Получаем цвет категории и преобразуем в CSS класс
const rawColor = item.categories?.nodes?.[0]?.color || '';
const categoryBgClass = extractColorClass(rawColor);
// Логика для больших плиток на десктопе
let isLarge = false;
let largePosition = '';
@@ -93,7 +98,7 @@ function extractColorClass(colorString: string): string {
<a href={postUrl} class="post-card-link">
<div class="post-image-container">
{item.featuredImage?.node?.sourceUrl ? (
<img loading="lazy"
<img
src={item.featuredImage.node.sourceUrl}
alt={item.featuredImage.node.altText || item.title}
width="400"
@@ -106,14 +111,12 @@ function extractColorClass(colorString: string): string {
<div class="post-image-placeholder"></div>
)}
{/* Рубрика в верхнем правом углу с цветом */}
{item.categories?.nodes?.[0]?.name && (
<div class={`post-category-badge ${categoryBgClass}`}>
{item.categories.nodes[0].name}
</div>
)}
{/* Оверлей с контентом */}
<div class="post-content-overlay">
<div class="post-meta-overlay">
<time
@@ -133,16 +136,15 @@ function extractColorClass(colorString: string): string {
{item.title}
</h3>
{item.author?.node?.name && (
{coauthorsNames && (
<div class="author-name" itemprop="author">
{item.author.node.name}
{coauthorsNames}
</div>
)}
</div>
</div>
</a>
{/* Скринридеру и SEO */}
<div class="sr-only">
<h3 itemprop="headline">
<a href={postUrl} itemprop="url">{item.title}</a>
@@ -158,4 +160,4 @@ function extractColorClass(colorString: string): string {
);
})}
</div>
</section>
</section>