core-maugli 1.2.9 → 1.2.11
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 +4 -3
- package/public/blackbox-1200.webp +0 -0
- package/public/blackbox-400.webp +0 -0
- package/public/blackbox-800.webp +0 -0
- package/public/img/default/autor_default-1200.webp +0 -0
- package/public/img/default/autor_default-400.webp +0 -0
- package/public/img/default/autor_default-800.webp +0 -0
- package/public/img/default/blog_default-1200.webp +0 -0
- package/public/img/default/blog_default-400.webp +0 -0
- package/public/img/default/blog_default-800.webp +0 -0
- package/public/img/default/default-1200.webp +0 -0
- package/public/img/default/default-400.webp +0 -0
- package/public/img/default/default-800.webp +0 -0
- package/public/img/default/previews/autor_default-1200.webp +0 -0
- package/public/img/default/previews/autor_default-400.webp +0 -0
- package/public/img/default/previews/autor_default-800.webp +0 -0
- package/public/img/default/previews/blog_default-1200.webp +0 -0
- package/public/img/default/previews/blog_default-400.webp +0 -0
- package/public/img/default/previews/blog_default-800.webp +0 -0
- package/public/img/default/previews/default-1200.webp +0 -0
- package/public/img/default/previews/default-400.webp +0 -0
- package/public/img/default/previews/default-800.webp +0 -0
- package/public/img/default/previews/product_default-1200.webp +0 -0
- package/public/img/default/previews/product_default-400.webp +0 -0
- package/public/img/default/previews/product_default-800.webp +0 -0
- package/public/img/default/previews/project_default-1200.webp +0 -0
- package/public/img/default/previews/project_default-400.webp +0 -0
- package/public/img/default/previews/project_default-800.webp +0 -0
- package/public/img/default/previews/rubric_default-1200.webp +0 -0
- package/public/img/default/previews/rubric_default-400.webp +0 -0
- package/public/img/default/previews/rubric_default-800.webp +0 -0
- package/public/img/default/previews/test-1200.webp +0 -0
- package/public/img/default/previews/test-400.webp +0 -0
- package/public/img/default/previews/test-800.webp +0 -0
- package/public/img/default/previews/test2-1200.webp +0 -0
- package/public/img/default/previews/test2-400.webp +0 -0
- package/public/img/default/previews/test2-800.webp +0 -0
- package/public/img/default/product_default-1200.webp +0 -0
- package/public/img/default/product_default-400.webp +0 -0
- package/public/img/default/product_default-800.webp +0 -0
- package/public/img/default/project_default-1200.webp +0 -0
- package/public/img/default/project_default-400.webp +0 -0
- package/public/img/default/project_default-800.webp +0 -0
- package/public/img/default/rubric_default-1200.webp +0 -0
- package/public/img/default/rubric_default-400.webp +0 -0
- package/public/img/default/rubric_default-800.webp +0 -0
- package/public/img/default/rubric_default.webp +0 -0
- package/public/img/default/test-1200.webp +0 -0
- package/public/img/default/test-400.webp +0 -0
- package/public/img/default/test-800.webp +0 -0
- package/public/img/default/test2-1200.webp +0 -0
- package/public/img/default/test2-400.webp +0 -0
- package/public/img/default/test2-800.webp +0 -0
- package/public/img/examples/authors/anna-1200.webp +0 -0
- package/public/img/examples/authors/anna-400.webp +0 -0
- package/public/img/examples/authors/anna-800.webp +0 -0
- package/public/img/examples/authors/carlos-1200.webp +0 -0
- package/public/img/examples/authors/carlos-400.webp +0 -0
- package/public/img/examples/authors/carlos-800.webp +0 -0
- package/public/img/examples/authors/daria-1200.webp +0 -0
- package/public/img/examples/authors/daria-400.webp +0 -0
- package/public/img/examples/authors/daria-800.webp +0 -0
- package/public/img/examples/authors/dmitry-1200.webp +0 -0
- package/public/img/examples/authors/dmitry-400.webp +0 -0
- package/public/img/examples/authors/dmitry-800.webp +0 -0
- package/public/img/examples/authors/igor-1200.webp +0 -0
- package/public/img/examples/authors/igor-400.webp +0 -0
- package/public/img/examples/authors/igor-800.webp +0 -0
- package/public/img/examples/authors/john-1200.webp +0 -0
- package/public/img/examples/authors/john-400.webp +0 -0
- package/public/img/examples/authors/john-800.webp +0 -0
- package/public/img/examples/blog/post-1-avtomatizaciya-marketinga-kak-ii-osvobozhdaet-predprinimatelei-ot-cifrovogo-rabstva-1200.webp +0 -0
- package/public/img/examples/blog/post-1-avtomatizaciya-marketinga-kak-ii-osvobozhdaet-predprinimatelei-ot-cifrovogo-rabstva-400.webp +0 -0
- package/public/img/examples/blog/post-1-avtomatizaciya-marketinga-kak-ii-osvobozhdaet-predprinimatelei-ot-cifrovogo-rabstva-800.webp +0 -0
- package/public/img/examples/blog/post-2-avtomatizaciya-kontenta-kak-neiroseti-ubivayut-perfekcionizm-v-biznese-1200.webp +0 -0
- package/public/img/examples/blog/post-2-avtomatizaciya-kontenta-kak-neiroseti-ubivayut-perfekcionizm-v-biznese-400.webp +0 -0
- package/public/img/examples/blog/post-2-avtomatizaciya-kontenta-kak-neiroseti-ubivayut-perfekcionizm-v-biznese-800.webp +0 -0
- package/public/img/examples/blog/post-3-laik-ne-valyuta-kak-avtomatizaciya-marketinga-spasaet-ot-lozhnyh-metrik-1200.webp +0 -0
- package/public/img/examples/blog/post-3-laik-ne-valyuta-kak-avtomatizaciya-marketinga-spasaet-ot-lozhnyh-metrik-400.webp +0 -0
- package/public/img/examples/blog/post-3-laik-ne-valyuta-kak-avtomatizaciya-marketinga-spasaet-ot-lozhnyh-metrik-800.webp +0 -0
- package/public/img/examples/blog/post-5-5-fatalnyh-oshibok-marketinga-kotorye-ubivayut-startapy-na-starte-1200.webp +0 -0
- package/public/img/examples/blog/post-5-5-fatalnyh-oshibok-marketinga-kotorye-ubivayut-startapy-na-starte-400.webp +0 -0
- package/public/img/examples/blog/post-5-5-fatalnyh-oshibok-marketinga-kotorye-ubivayut-startapy-na-starte-800.webp +0 -0
- package/public/img/examples/blog/post-6-5-strategii-kontent-marketinga-dlya-startapov-avtomatizaciya-i-revolyuciya-1200.webp +0 -0
- package/public/img/examples/blog/post-6-5-strategii-kontent-marketinga-dlya-startapov-avtomatizaciya-i-revolyuciya-400.webp +0 -0
- package/public/img/examples/blog/post-6-5-strategii-kontent-marketinga-dlya-startapov-avtomatizaciya-i-revolyuciya-800.webp +0 -0
- package/public/img/examples/blog/post-7-viralnyi-kontent-ne-udacha-a-strategiya-avtomatizaciya-marketinga-1200.webp +0 -0
- package/public/img/examples/blog/post-7-viralnyi-kontent-ne-udacha-a-strategiya-avtomatizaciya-marketinga-400.webp +0 -0
- package/public/img/examples/blog/post-7-viralnyi-kontent-ne-udacha-a-strategiya-avtomatizaciya-marketinga-800.webp +0 -0
- package/public/img/examples/blog/post-agent-experience-mcp-biznes-v-epohu-ii-agentov-1200.webp +0 -0
- package/public/img/examples/blog/post-agent-experience-mcp-biznes-v-epohu-ii-agentov-400.webp +0 -0
- package/public/img/examples/blog/post-agent-experience-mcp-biznes-v-epohu-ii-agentov-800.webp +0 -0
- package/public/img/examples/blog/post_11-1200.webp +0 -0
- package/public/img/examples/blog/post_11-400.webp +0 -0
- package/public/img/examples/blog/post_11-800.webp +0 -0
- package/public/img/examples/blog/post_12-1200.webp +0 -0
- package/public/img/examples/blog/post_12-400.webp +0 -0
- package/public/img/examples/blog/post_12-800.webp +0 -0
- package/public/img/examples/blog/post_1_jsonld_guide-1200.webp +0 -0
- package/public/img/examples/blog/post_1_jsonld_guide-400.webp +0 -0
- package/public/img/examples/blog/post_1_jsonld_guide-800.webp +0 -0
- package/public/img/examples/blog/previews/post-1-avtomatizaciya-marketinga-kak-ii-osvobozhdaet-predprinimatelei-ot-cifrovogo-rabstva-1200.webp +0 -0
- package/public/img/examples/blog/previews/post-1-avtomatizaciya-marketinga-kak-ii-osvobozhdaet-predprinimatelei-ot-cifrovogo-rabstva-400.webp +0 -0
- package/public/img/examples/blog/previews/post-1-avtomatizaciya-marketinga-kak-ii-osvobozhdaet-predprinimatelei-ot-cifrovogo-rabstva-800.webp +0 -0
- package/public/img/examples/blog/previews/post-2-avtomatizaciya-kontenta-kak-neiroseti-ubivayut-perfekcionizm-v-biznese-1200.webp +0 -0
- package/public/img/examples/blog/previews/post-2-avtomatizaciya-kontenta-kak-neiroseti-ubivayut-perfekcionizm-v-biznese-400.webp +0 -0
- package/public/img/examples/blog/previews/post-2-avtomatizaciya-kontenta-kak-neiroseti-ubivayut-perfekcionizm-v-biznese-800.webp +0 -0
- package/public/img/examples/blog/previews/post-3-laik-ne-valyuta-kak-avtomatizaciya-marketinga-spasaet-ot-lozhnyh-metrik-1200.webp +0 -0
- package/public/img/examples/blog/previews/post-3-laik-ne-valyuta-kak-avtomatizaciya-marketinga-spasaet-ot-lozhnyh-metrik-400.webp +0 -0
- package/public/img/examples/blog/previews/post-3-laik-ne-valyuta-kak-avtomatizaciya-marketinga-spasaet-ot-lozhnyh-metrik-800.webp +0 -0
- package/public/img/examples/blog/previews/post-5-5-fatalnyh-oshibok-marketinga-kotorye-ubivayut-startapy-na-starte-1200.webp +0 -0
- package/public/img/examples/blog/previews/post-5-5-fatalnyh-oshibok-marketinga-kotorye-ubivayut-startapy-na-starte-400.webp +0 -0
- package/public/img/examples/blog/previews/post-5-5-fatalnyh-oshibok-marketinga-kotorye-ubivayut-startapy-na-starte-800.webp +0 -0
- package/public/img/examples/blog/previews/post-6-5-strategii-kontent-marketinga-dlya-startapov-avtomatizaciya-i-revolyuciya-1200.webp +0 -0
- package/public/img/examples/blog/previews/post-6-5-strategii-kontent-marketinga-dlya-startapov-avtomatizaciya-i-revolyuciya-400.webp +0 -0
- package/public/img/examples/blog/previews/post-6-5-strategii-kontent-marketinga-dlya-startapov-avtomatizaciya-i-revolyuciya-800.webp +0 -0
- package/public/img/examples/blog/previews/post-7-viralnyi-kontent-ne-udacha-a-strategiya-avtomatizaciya-marketinga-1200.webp +0 -0
- package/public/img/examples/blog/previews/post-7-viralnyi-kontent-ne-udacha-a-strategiya-avtomatizaciya-marketinga-400.webp +0 -0
- package/public/img/examples/blog/previews/post-7-viralnyi-kontent-ne-udacha-a-strategiya-avtomatizaciya-marketinga-800.webp +0 -0
- package/public/img/examples/blog/previews/post-agent-experience-mcp-biznes-v-epohu-ii-agentov-1200.webp +0 -0
- package/public/img/examples/blog/previews/post-agent-experience-mcp-biznes-v-epohu-ii-agentov-400.webp +0 -0
- package/public/img/examples/blog/previews/post-agent-experience-mcp-biznes-v-epohu-ii-agentov-800.webp +0 -0
- package/public/img/examples/blog/previews/post_11-1200.webp +0 -0
- package/public/img/examples/blog/previews/post_11-400.webp +0 -0
- package/public/img/examples/blog/previews/post_11-800.webp +0 -0
- package/public/img/examples/blog/previews/post_12-1200.webp +0 -0
- package/public/img/examples/blog/previews/post_12-400.webp +0 -0
- package/public/img/examples/blog/previews/post_12-800.webp +0 -0
- package/public/img/examples/blog/previews/post_1_jsonld_guide-1200.webp +0 -0
- package/public/img/examples/blog/previews/post_1_jsonld_guide-400.webp +0 -0
- package/public/img/examples/blog/previews/post_1_jsonld_guide-800.webp +0 -0
- package/public/img/examples/blog/previews/test-post-1200.webp +0 -0
- package/public/img/examples/blog/previews/test-post-400.webp +0 -0
- package/public/img/examples/blog/previews/test-post-800.webp +0 -0
- package/public/img/examples/blog/test-post-1200.webp +0 -0
- package/public/img/examples/blog/test-post-400.webp +0 -0
- package/public/img/examples/blog/test-post-800.webp +0 -0
- package/public/img/examples/products/previews/product_1-1200.webp +0 -0
- package/public/img/examples/products/previews/product_1-400.webp +0 -0
- package/public/img/examples/products/previews/product_1-800.webp +0 -0
- package/public/img/examples/products/previews/product_2-1200.webp +0 -0
- package/public/img/examples/products/previews/product_2-400.webp +0 -0
- package/public/img/examples/products/previews/product_2-800.webp +0 -0
- package/public/img/examples/products/product_1-1200.webp +0 -0
- package/public/img/examples/products/product_1-400.webp +0 -0
- package/public/img/examples/products/product_1-800.webp +0 -0
- package/public/img/examples/products/product_2-1200.webp +0 -0
- package/public/img/examples/products/product_2-400.webp +0 -0
- package/public/img/examples/products/product_2-800.webp +0 -0
- package/public/img/examples/projects/previews/project_1-1200.webp +0 -0
- package/public/img/examples/projects/previews/project_1-400.webp +0 -0
- package/public/img/examples/projects/previews/project_1-800.webp +0 -0
- package/public/img/examples/projects/previews/project_2-1200.webp +0 -0
- package/public/img/examples/projects/previews/project_2-400.webp +0 -0
- package/public/img/examples/projects/previews/project_2-800.webp +0 -0
- package/public/img/examples/projects/project_1-1200.webp +0 -0
- package/public/img/examples/projects/project_1-400.webp +0 -0
- package/public/img/examples/projects/project_1-800.webp +0 -0
- package/public/img/examples/projects/project_2-1200.webp +0 -0
- package/public/img/examples/projects/project_2-400.webp +0 -0
- package/public/img/examples/projects/project_2-800.webp +0 -0
- package/public/img/page-images/blog_default-1200.webp +0 -0
- package/public/img/page-images/blog_default-400.webp +0 -0
- package/public/img/page-images/blog_default-800.webp +0 -0
- package/scripts/generate-previews.js +22 -14
- package/src/components/RubricCard.astro +88 -7
- package/src/content/tags/ai-business.mdx +1 -3
- package/src/content/tags/automation.mdx +1 -3
- package/src/content/tags/content-strategy.mdx +1 -3
package/package.json
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
"name": "core-maugli",
|
3
3
|
"description": "Astro & Tailwind CSS blog theme for Maugli.",
|
4
4
|
"type": "module",
|
5
|
-
"version": "1.2.
|
5
|
+
"version": "1.2.11",
|
6
6
|
"license": "GPL-3.0-or-later OR Commercial",
|
7
7
|
"repository": {
|
8
8
|
"type": "git",
|
@@ -19,9 +19,10 @@
|
|
19
19
|
],
|
20
20
|
"scripts": {
|
21
21
|
"typograf": "node typograf-batch.js",
|
22
|
-
"dev": "astro dev",
|
22
|
+
"dev": "node resize-all.cjs && node scripts/generate-previews.js && astro dev",
|
23
|
+
"prestart": "node resize-all.cjs && node scripts/generate-previews.js",
|
23
24
|
"start": "astro dev",
|
24
|
-
"build": "node typograf-batch.js && node scripts/verify-assets.js && node scripts/generate-previews.js && astro build",
|
25
|
+
"build": "node resize-all.cjs && node typograf-batch.js && node scripts/verify-assets.js && node scripts/generate-previews.js && astro build",
|
25
26
|
"test": "node tests/examplesFilter.test.ts",
|
26
27
|
"astro": "astro",
|
27
28
|
"featured:add": "node scripts/featured.js add",
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
package/public/img/examples/blog/post-agent-experience-mcp-biznes-v-epohu-ii-agentov-1200.webp
ADDED
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -103,6 +103,8 @@ function extractImagePaths() {
|
|
103
103
|
const items = fs.readdirSync(defaultDir);
|
104
104
|
for (const item of items) {
|
105
105
|
if (item.match(/\.(webp|jpg|jpeg|png)$/i)) {
|
106
|
+
// Исключаем изображения авторов и рубрик
|
107
|
+
if (item.includes('autor') || item.includes('author') || item.includes('rubric')) continue;
|
106
108
|
imagePaths.add(`/img/default/${item}`);
|
107
109
|
}
|
108
110
|
}
|
@@ -141,42 +143,44 @@ function cleanupExistingPreviews() {
|
|
141
143
|
// Функция для создания превьюшки
|
142
144
|
async function createPreview(imagePath) {
|
143
145
|
const fullImagePath = path.join(rootDir, 'public', imagePath.replace(/^\//, ''));
|
144
|
-
|
146
|
+
|
145
147
|
if (!fs.existsSync(fullImagePath)) {
|
146
148
|
console.warn(`Image not found: ${fullImagePath}`);
|
147
149
|
return;
|
148
150
|
}
|
149
|
-
|
151
|
+
|
150
152
|
const dir = path.dirname(fullImagePath);
|
151
153
|
const ext = path.extname(fullImagePath);
|
152
154
|
const name = path.basename(fullImagePath, ext);
|
153
155
|
const previewPath = path.join(dir, 'previews', `${name}${ext}`);
|
154
|
-
|
156
|
+
|
155
157
|
// Определяем размер превью в зависимости от типа изображения
|
156
158
|
let previewWidth, previewHeight;
|
157
159
|
if (imagePath.includes('/img/default/') && (name.includes('rubric') || name.includes('tag'))) {
|
158
|
-
// Для изображений рубрик используем меньший размер
|
159
160
|
previewWidth = rubricPreviewWidth;
|
160
161
|
previewHeight = rubricPreviewHeight;
|
161
162
|
console.log(`Creating rubric preview (${previewWidth}x${previewHeight}): ${name}`);
|
162
163
|
} else {
|
163
|
-
// Для блог-постов и других изображений используем стандартный размер
|
164
164
|
previewWidth = blogPreviewWidth;
|
165
165
|
previewHeight = blogPreviewHeight;
|
166
166
|
console.log(`Creating blog preview (${previewWidth}x${previewHeight}): ${name}`);
|
167
167
|
}
|
168
|
-
|
168
|
+
|
169
169
|
// Создаем папку previews если её нет
|
170
170
|
const previewDir = path.dirname(previewPath);
|
171
171
|
if (!fs.existsSync(previewDir)) {
|
172
172
|
fs.mkdirSync(previewDir, { recursive: true });
|
173
173
|
}
|
174
|
-
|
174
|
+
|
175
|
+
// Если превью уже существует — пропускаем генерацию
|
176
|
+
if (fs.existsSync(previewPath)) {
|
177
|
+
// console.log(`Preview already exists: ${previewPath}`);
|
178
|
+
return;
|
179
|
+
}
|
175
180
|
try {
|
176
181
|
await sharp(fullImagePath)
|
177
182
|
.resize(previewWidth, previewHeight, { fit: 'cover' })
|
178
183
|
.toFile(previewPath);
|
179
|
-
|
180
184
|
console.log(`Preview created: ${previewPath}`);
|
181
185
|
} catch (error) {
|
182
186
|
console.error(`Error processing ${fullImagePath}:`, error.message);
|
@@ -185,18 +189,22 @@ async function createPreview(imagePath) {
|
|
185
189
|
|
186
190
|
// Основная функция
|
187
191
|
async function generatePreviews() {
|
188
|
-
|
189
|
-
|
190
|
-
|
192
|
+
// Очистка превью только если явно указано (например, через переменную)
|
193
|
+
const CLEAN_PREVIEWS = process.env.CLEAN_PREVIEWS === '1';
|
194
|
+
if (CLEAN_PREVIEWS) {
|
195
|
+
console.log('Cleaning up existing previews...');
|
196
|
+
cleanupExistingPreviews();
|
197
|
+
}
|
198
|
+
|
191
199
|
console.log('Scanning content for images...');
|
192
200
|
const imagePaths = extractImagePaths();
|
193
|
-
|
201
|
+
|
194
202
|
console.log(`Found ${imagePaths.length} images to process`);
|
195
|
-
|
203
|
+
|
196
204
|
for (const imagePath of imagePaths) {
|
197
205
|
await createPreview(imagePath);
|
198
206
|
}
|
199
|
-
|
207
|
+
|
200
208
|
console.log('Preview generation completed!');
|
201
209
|
}
|
202
210
|
|
@@ -94,24 +94,95 @@ const isBrandDate = isToday || isYesterday;
|
|
94
94
|
function getPreviewImageSrc(imageSrc: string): string {
|
95
95
|
if (!imageSrc) return maugliConfig.defaultRubricImage;
|
96
96
|
|
97
|
-
//
|
97
|
+
// Если это изображение по умолчанию, возвращаем его превью напрямую
|
98
|
+
if (imageSrc === maugliConfig.defaultRubricImage) {
|
99
|
+
return '/img/default/previews/rubric_default.webp';
|
100
|
+
}
|
101
|
+
|
102
|
+
// Для кастомных изображений проверяем, есть ли превью
|
98
103
|
const pathParts = imageSrc.split('/');
|
99
104
|
const fileName = pathParts.pop();
|
100
105
|
const directory = pathParts.join('/');
|
101
106
|
const previewPath = `${directory}/previews/${fileName}`;
|
102
107
|
|
108
|
+
// Убеждаемся, что путь абсолютный (начинается с /)
|
109
|
+
const absolutePreviewPath = previewPath.startsWith('/') ? previewPath : `/${previewPath}`;
|
110
|
+
|
103
111
|
// Возвращаем путь к превью (браузер покажет оригинал, если превью не найдено)
|
104
|
-
return
|
112
|
+
return absolutePreviewPath;
|
113
|
+
}
|
114
|
+
|
115
|
+
// Всегда используем дефолтное изображение для рубрик
|
116
|
+
const previewImageSrc = '/img/default/previews/rubric_default.webp';
|
117
|
+
|
118
|
+
// Список стоп-слов (предлоги, союзы, знаки)
|
119
|
+
const stopWords = [
|
120
|
+
'и',
|
121
|
+
'в',
|
122
|
+
'на',
|
123
|
+
'с',
|
124
|
+
'по',
|
125
|
+
'от',
|
126
|
+
'до',
|
127
|
+
'за',
|
128
|
+
'над',
|
129
|
+
'под',
|
130
|
+
'о',
|
131
|
+
'об',
|
132
|
+
'у',
|
133
|
+
'для',
|
134
|
+
'к',
|
135
|
+
'ко',
|
136
|
+
'из',
|
137
|
+
'без',
|
138
|
+
'при',
|
139
|
+
'а',
|
140
|
+
'но',
|
141
|
+
'или',
|
142
|
+
'да',
|
143
|
+
'же',
|
144
|
+
'ли',
|
145
|
+
'бы',
|
146
|
+
'не',
|
147
|
+
'то',
|
148
|
+
'же',
|
149
|
+
'the',
|
150
|
+
'of',
|
151
|
+
'to',
|
152
|
+
'in',
|
153
|
+
'on',
|
154
|
+
'at',
|
155
|
+
'by',
|
156
|
+
'for',
|
157
|
+
'with',
|
158
|
+
'from',
|
159
|
+
'as',
|
160
|
+
'an',
|
161
|
+
'or',
|
162
|
+
'but',
|
163
|
+
'&'
|
164
|
+
];
|
165
|
+
|
166
|
+
function getRubricInitials(title: string): string {
|
167
|
+
if (!title) return '';
|
168
|
+
// Удаляем лишние символы
|
169
|
+
const clean = title.replace(/[^\wа-яА-ЯёЁ\s]/gi, ' ');
|
170
|
+
const words = clean.split(/\s+/).filter(Boolean);
|
171
|
+
// Берём первые буквы каждого слова, кроме стоп-слов
|
172
|
+
const initials = words
|
173
|
+
.filter((word) => !stopWords.includes(word.toLowerCase()))
|
174
|
+
.slice(0, 2)
|
175
|
+
.map((word) => word[0]?.toUpperCase() || '')
|
176
|
+
.join('');
|
177
|
+
return initials;
|
105
178
|
}
|
106
179
|
|
107
|
-
const
|
108
|
-
const previewImageSrc = getPreviewImageSrc(imageSrc);
|
180
|
+
const rubricInitials = getRubricInitials(title);
|
109
181
|
|
110
182
|
// Debug информация только в development режиме
|
111
183
|
if (import.meta.env.DEV) {
|
112
184
|
console.log('RubricCard Debug:', {
|
113
185
|
title,
|
114
|
-
originalImageSrc: imageSrc,
|
115
186
|
previewImageSrc,
|
116
187
|
defaultRubricImage: maugliConfig.defaultRubricImage
|
117
188
|
});
|
@@ -123,8 +194,18 @@ if (import.meta.env.DEV) {
|
|
123
194
|
class={`w-full h-[195px] border border-[var(--border-main)] rounded-custom card-bg hover:card-shadow hover:-translate-y-1 transition-all duration-300 p-6 flex flex-row gap-4 items-start ${className}`}
|
124
195
|
>
|
125
196
|
<!-- Левая часть: картинка и дата -->
|
126
|
-
<div class="flex flex-col items-end gap-2 w-[105px] h-[147px]">
|
127
|
-
<img src={previewImageSrc} alt={
|
197
|
+
<div class="flex flex-col items-end gap-2 w-[105px] h-[147px] relative">
|
198
|
+
<img src={previewImageSrc} alt={title} class="w-[105px] h-[107px] object-cover rounded-custom" loading="lazy" />
|
199
|
+
{
|
200
|
+
rubricInitials && (
|
201
|
+
<span style="position:absolute;left:0;top:0;width:105px;height:107px;display:flex;align-items:center;justify-content:center;pointer-events:none;z-index:2;">
|
202
|
+
<span style="position:absolute;left:0;top:0;width:105px;height:107px;background:rgba(0,0,0,0.10);border-radius:inherit;z-index:1;" />
|
203
|
+
<span style="position:relative;z-index:2;font-size:48px;font-weight:700;font-family:inherit;color:var(--brand-color);letter-spacing:2px;">
|
204
|
+
{rubricInitials}
|
205
|
+
</span>
|
206
|
+
</span>
|
207
|
+
)
|
208
|
+
}
|
128
209
|
<div class="flex flex-col items-end gap-1 w-[74px] h-[32px]">
|
129
210
|
<span class={`flex items-center gap-1 text-[12px] text-right ${isBrandDate ? 'text-[var(--brand-color)]' : 'text-[var(--text-muted)]'}`}>
|
130
211
|
<svg
|
@@ -1,9 +1,7 @@
|
|
1
1
|
---
|
2
2
|
title: AI в бизнесе
|
3
3
|
description: "Обзоры технологий (LLM, GPT, Claude и др.). Кейсы применения AI в бизнесе. Тренды в автоматизации контента."
|
4
|
-
|
5
|
-
src: '/img/default/rubric_default.webp'
|
6
|
-
alt: AI в бизнесе
|
4
|
+
|
7
5
|
isRubric: true
|
8
6
|
isFeatured: false
|
9
7
|
jsonld:
|
@@ -1,9 +1,7 @@
|
|
1
1
|
---
|
2
2
|
title: Автоматизация бизнеса
|
3
3
|
description: "Workflow и интеграции (Airtable, Supabase, автопостинг). AI-редакторы и сценарии. «Редакция без людей» — практика и инструменты."
|
4
|
-
|
5
|
-
src: '/img/default/rubric_default.webp'
|
6
|
-
alt: Автоматизация бизнеса
|
4
|
+
|
7
5
|
isRubric: true
|
8
6
|
isFeatured: false
|
9
7
|
jsonld:
|