core-maugli 1.2.22 → 1.2.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
@@ -137,17 +137,17 @@ let defaultAuthorName = defaultAuthor.data.name;
|
|
137
137
|
<meta http-equiv="x-ua-compatible" content="ie=edge" />
|
138
138
|
|
139
139
|
<!-- Font Loading Strategy - Non-blocking -->
|
140
|
-
<link
|
141
|
-
rel="preload"
|
142
|
-
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap"
|
143
|
-
as="style"
|
144
|
-
onload="this.onload=null;this.rel='stylesheet'"
|
140
|
+
<link
|
141
|
+
rel="preload"
|
142
|
+
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap"
|
143
|
+
as="style"
|
144
|
+
onload="this.onload=null;this.rel='stylesheet'"
|
145
145
|
/>
|
146
|
-
<link
|
147
|
-
rel="preload"
|
148
|
-
href="https://fonts.googleapis.com/css2?family=Geologica:wght@400;500;600&display=swap"
|
149
|
-
as="style"
|
150
|
-
onload="this.onload=null;this.rel='stylesheet'"
|
146
|
+
<link
|
147
|
+
rel="preload"
|
148
|
+
href="https://fonts.googleapis.com/css2?family=Geologica:wght@400;500;600&display=swap"
|
149
|
+
as="style"
|
150
|
+
onload="this.onload=null;this.rel='stylesheet'"
|
151
151
|
/>
|
152
152
|
<noscript>
|
153
153
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap" />
|
@@ -1,7 +1,4 @@
|
|
1
1
|
---
|
2
|
-
import fs from 'fs';
|
3
|
-
import path from 'path';
|
4
|
-
import { fileURLToPath } from 'url';
|
5
2
|
import { maugliConfig } from '../config/maugli.config';
|
6
3
|
import FormattedDate from './FormattedDate.astro';
|
7
4
|
|
@@ -16,7 +13,7 @@ type Props = {
|
|
16
13
|
headingLevel?: 'h2' | 'h3';
|
17
14
|
isFeatured?: boolean;
|
18
15
|
class?: string;
|
19
|
-
type?: string;
|
16
|
+
type?: string;
|
20
17
|
};
|
21
18
|
|
22
19
|
const { href, title, image, seo, publishDate, excerpt, description, headingLevel = 'h2', isFeatured = false, class: className, type } = Astro.props;
|
@@ -35,62 +32,8 @@ const baseImage =
|
|
35
32
|
? maugliConfig.defaultProductImage
|
36
33
|
: maugliConfig.seo.defaultImage);
|
37
34
|
|
38
|
-
// Генерируем адаптивные версии изображений
|
39
|
-
function getResponsiveImages(imagePath: string) {
|
40
|
-
const basePath = imagePath.replace(/\.(webp|jpg|jpeg|png)$/i, '');
|
41
|
-
const extension = imagePath.match(/\.(webp|jpg|jpeg|png)$/i)?.[0] || '.webp';
|
42
|
-
|
43
|
-
// Проверяем существование адаптивных версий
|
44
|
-
const __filename = fileURLToPath(import.meta.url);
|
45
|
-
const projectRoot = path.resolve(path.dirname(__filename), '../..');
|
46
|
-
|
47
|
-
const variants = [
|
48
|
-
{ suffix: '-400', width: '400w' },
|
49
|
-
{ suffix: '-800', width: '800w' },
|
50
|
-
{ suffix: '-1200', width: '1200w' }
|
51
|
-
];
|
52
|
-
|
53
|
-
const srcsetItems = [];
|
54
|
-
|
55
|
-
// Добавляем адаптивные версии, если они существуют
|
56
|
-
for (const variant of variants) {
|
57
|
-
const variantPath = `${basePath}${variant.suffix}${extension}`;
|
58
|
-
const filePath = path.join(projectRoot, 'public', variantPath.replace(/^\//, ''));
|
59
|
-
|
60
|
-
if (fs.existsSync(filePath)) {
|
61
|
-
srcsetItems.push(`${variantPath} ${variant.width}`);
|
62
|
-
}
|
63
|
-
}
|
64
|
-
|
65
|
-
// Всегда добавляем оригинальное изображение
|
66
|
-
srcsetItems.push(`${imagePath} 1200w`);
|
67
|
-
|
68
|
-
return {
|
69
|
-
src: imagePath,
|
70
|
-
srcset: srcsetItems.join(', '),
|
71
|
-
sizes: '(max-width: 768px) 100vw, (max-width: 1024px) 50vw, 400px'
|
72
|
-
};
|
73
|
-
}
|
74
|
-
|
75
|
-
const cardImage = getResponsiveImages(baseImage);
|
76
35
|
const cardImageAlt = seo?.image?.alt || image?.alt || title || 'Изображение';
|
77
36
|
|
78
|
-
// Используем уменьшенное превью, если оно существует
|
79
|
-
let previewImage;
|
80
|
-
if (cardImage.src) {
|
81
|
-
previewImage = cardImage.src.replace(/\/([^\/]+)$/, '/previews/$1');
|
82
|
-
|
83
|
-
const __filename = fileURLToPath(import.meta.url);
|
84
|
-
const projectRoot = path.resolve(path.dirname(__filename), '../..');
|
85
|
-
const previewFilePath = path.join(projectRoot, 'public', previewImage.replace(/^\//, ''));
|
86
|
-
|
87
|
-
if (!fs.existsSync(previewFilePath)) {
|
88
|
-
previewImage = undefined;
|
89
|
-
}
|
90
|
-
}
|
91
|
-
|
92
|
-
const finalImage = previewImage || cardImage.src;
|
93
|
-
|
94
37
|
// Определяем контент для отображения
|
95
38
|
const content = excerpt || description;
|
96
39
|
---
|
@@ -106,9 +49,7 @@ const content = excerpt || description;
|
|
106
49
|
<!-- Изображение -->
|
107
50
|
<div class="w-full aspect-[1200/630] bg-[var(--bg-muted)] overflow-hidden relative">
|
108
51
|
<img
|
109
|
-
src={
|
110
|
-
srcset={cardImage.srcset}
|
111
|
-
sizes={cardImage.sizes}
|
52
|
+
src={baseImage}
|
112
53
|
alt={cardImageAlt}
|
113
54
|
loading="lazy"
|
114
55
|
width="1200"
|
@@ -2,7 +2,6 @@
|
|
2
2
|
import { maugliConfig } from '../config/maugli.config';
|
3
3
|
import { LANGUAGES } from '../i18n/languages';
|
4
4
|
import AuthorLinksGroup from './AuthorLinksGroup.astro';
|
5
|
-
import OptimizedImage from './OptimizedImage.astro';
|
6
5
|
// Универсальный импорт словарей по доступным языкам
|
7
6
|
const dicts: Record<string, any> = {};
|
8
7
|
for (const lang of LANGUAGES) {
|
@@ -12,34 +12,20 @@ export interface Props {
|
|
12
12
|
quality?: number;
|
13
13
|
}
|
14
14
|
|
15
|
-
const {
|
16
|
-
src,
|
17
|
-
alt,
|
18
|
-
width,
|
19
|
-
height,
|
20
|
-
class: className = '',
|
21
|
-
loading = 'lazy',
|
22
|
-
decoding = 'async',
|
23
|
-
sizes,
|
24
|
-
priority = false,
|
25
|
-
quality = 75,
|
26
|
-
...rest
|
27
|
-
} = Astro.props;
|
15
|
+
const { src, alt, width, height, class: className = '', loading = 'lazy', decoding = 'async', sizes, priority = false, quality = 75, ...rest } = Astro.props;
|
28
16
|
|
29
17
|
// Generate responsive image variations with quality optimization
|
30
18
|
const generateSrcSet = (baseSrc: string) => {
|
31
19
|
const baseUrl = baseSrc.replace(/\.[^.]+$/, '');
|
32
20
|
const ext = 'webp'; // Always use WebP for better compression
|
33
|
-
|
21
|
+
|
34
22
|
const variations = [
|
35
23
|
{ width: 400, suffix: '-400' },
|
36
24
|
{ width: 800, suffix: '-800' },
|
37
25
|
{ width: 1200, suffix: '-1200' }
|
38
26
|
];
|
39
|
-
|
40
|
-
return variations
|
41
|
-
.map(({ width, suffix }) => `${baseUrl}${suffix}.${ext} ${width}w`)
|
42
|
-
.join(', ');
|
27
|
+
|
28
|
+
return variations.map(({ width, suffix }) => `${baseUrl}${suffix}.${ext} ${width}w`).join(', ');
|
43
29
|
};
|
44
30
|
|
45
31
|
const srcSet = generateSrcSet(src);
|
@@ -62,6 +48,4 @@ const shouldPreload = priority && loading === 'eager';
|
|
62
48
|
{...rest}
|
63
49
|
/>
|
64
50
|
|
65
|
-
{priority &&
|
66
|
-
<link rel="preload" as="image" href={src} type="image/webp" />
|
67
|
-
)}
|
51
|
+
{priority && <link rel="preload" as="image" href={src} type="image/webp" />}
|
@@ -0,0 +1,46 @@
|
|
1
|
+
---
|
2
|
+
export interface Props {
|
3
|
+
src: string;
|
4
|
+
alt: string;
|
5
|
+
width?: number;
|
6
|
+
height?: number;
|
7
|
+
class?: string;
|
8
|
+
loading?: 'lazy' | 'eager';
|
9
|
+
decoding?: 'async' | 'sync' | 'auto';
|
10
|
+
sizes?: string;
|
11
|
+
quality?: number;
|
12
|
+
format?: 'webp' | 'avif' | 'jpeg' | 'png';
|
13
|
+
}
|
14
|
+
|
15
|
+
const {
|
16
|
+
src,
|
17
|
+
alt,
|
18
|
+
width = 1200,
|
19
|
+
height = 630,
|
20
|
+
class: className = '',
|
21
|
+
loading = 'lazy',
|
22
|
+
decoding = 'async',
|
23
|
+
sizes = '(max-width: 768px) 100vw, (max-width: 1024px) 50vw, 400px',
|
24
|
+
quality = 75,
|
25
|
+
format = 'webp',
|
26
|
+
...rest
|
27
|
+
} = Astro.props;
|
28
|
+
|
29
|
+
// Простая стратегия - используем базовое изображение и не генерируем srcset для несуществующих файлов
|
30
|
+
const optimizedSrc = src;
|
31
|
+
|
32
|
+
// Генерируем srcset только если есть базовое изображение
|
33
|
+
const generateSrcSet = (baseSrc: string) => {
|
34
|
+
if (baseSrc.startsWith('http')) {
|
35
|
+
return baseSrc;
|
36
|
+
}
|
37
|
+
|
38
|
+
// Возвращаем только базовое изображение без попыток создания srcset
|
39
|
+
// Responsive варианты будут обработаны build процессом
|
40
|
+
return baseSrc;
|
41
|
+
};
|
42
|
+
|
43
|
+
const srcSet = generateSrcSet(src);
|
44
|
+
---
|
45
|
+
|
46
|
+
<img src={optimizedSrc} alt={alt} width={width} height={height} class={className} loading={loading} decoding={decoding} sizes={sizes} {...rest} />
|