core-maugli 1.2.64 → 1.2.65

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
@@ -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.64",
5
+ "version": "1.2.65",
6
6
  "license": "GPL-3.0-or-later OR Commercial",
7
7
  "repository": {
8
8
  "type": "git",
Binary file
Binary file
Binary file
@@ -1,6 +1,8 @@
1
1
  ---
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+ import { fileURLToPath } from 'url';
2
5
  import { maugliConfig } from '../config/maugli.config';
3
-
4
6
  import { LANGUAGES } from '../i18n/languages';
5
7
 
6
8
  // Карточка баннера продукта для боковой панели статьи/проекта
@@ -8,10 +10,71 @@ import { LANGUAGES } from '../i18n/languages';
8
10
  const { product } = Astro.props;
9
11
  const { seo, image, title, id, productLink } = product?.data || {};
10
12
 
11
- // Дефолтная картинка всегда
12
- const productID = product?.data?.productID;
13
- let bannerImage = productID ? `/${productID}.webp` : maugliConfig.defaultProductImage;
14
- if (!bannerImage) bannerImage = maugliConfig.defaultProductImage;
13
+ // Функция для получения изображения продукта с приоритетом превью 400px
14
+ function getProductBannerImage(product: any, defaultImage: string): string {
15
+ const { image, productID } = product?.data || {};
16
+
17
+ // Если есть изображение в контенте продукта - используем его с превью логикой
18
+ if (image?.src) {
19
+ const imageSrc = image.src;
20
+
21
+ const __filename = fileURLToPath(import.meta.url);
22
+ const projectRoot = path.resolve(path.dirname(__filename), '../..');
23
+
24
+ // Получаем путь к файлу и имя файла
25
+ const pathParts = imageSrc.split('/');
26
+ const fileName = pathParts.pop() || '';
27
+ const directory = pathParts.join('/');
28
+ const baseName = fileName.replace(/\.(webp|jpg|jpeg|png)$/i, '');
29
+ const extension = fileName.match(/\.(webp|jpg|jpeg|png)$/i)?.[0] || '.webp';
30
+
31
+ // Приоритет 1: превью 400px версия
32
+ const preview400Path = `${directory}/${baseName}-400${extension}`;
33
+ const preview400FilePath = path.join(projectRoot, 'public', preview400Path.replace(/^\//, ''));
34
+ if (fs.existsSync(preview400FilePath)) {
35
+ return preview400Path;
36
+ }
37
+
38
+ // Приоритет 2: превью версия в папке previews
39
+ const previewPath = `${directory}/previews/${fileName}`;
40
+ const previewFilePath = path.join(projectRoot, 'public', previewPath.replace(/^\//, ''));
41
+ if (fs.existsSync(previewFilePath)) {
42
+ return previewPath;
43
+ }
44
+
45
+ // Приоритет 3: оригинальное изображение из контента
46
+ const originalFilePath = path.join(projectRoot, 'public', imageSrc.replace(/^\//, ''));
47
+ if (fs.existsSync(originalFilePath)) {
48
+ return imageSrc;
49
+ }
50
+ }
51
+
52
+ // Fallback: если нет изображения в контенте, пробуем по productID (старая логика)
53
+ if (productID) {
54
+ const __filename = fileURLToPath(import.meta.url);
55
+ const projectRoot = path.resolve(path.dirname(__filename), '../..');
56
+
57
+ // Проверяем стандартные места для productID
58
+ const possiblePaths = [
59
+ `/img/default/previews/${productID}-400.webp`,
60
+ `/img/default/previews/${productID}.webp`,
61
+ `/${productID}.webp`,
62
+ `/img/default/${productID}.webp`
63
+ ];
64
+
65
+ for (const testPath of possiblePaths) {
66
+ const testFilePath = path.join(projectRoot, 'public', testPath.replace(/^\//, ''));
67
+ if (fs.existsSync(testFilePath)) {
68
+ return testPath;
69
+ }
70
+ }
71
+ }
72
+
73
+ // Финальный fallback: дефолтное изображение
74
+ return defaultImage;
75
+ }
76
+
77
+ const bannerImage = getProductBannerImage(product, maugliConfig.defaultProductImage);
15
78
  // Кнопка: если есть productLink, то ссылка, иначе неактивная
16
79
  const buttonHref = productLink && productLink.trim() ? productLink : null;
17
80
  const isExternal = buttonHref && /^https?:\/\//.test(buttonHref);
@@ -1,35 +1,35 @@
1
1
  ---
2
- title: "Rubrics"
3
- slug: "rubrics"
2
+ title: "Рубрики и теги"
3
+ slug: "tags"
4
4
  image:
5
5
  src: "/defaultRubricImage.webp"
6
6
  seo:
7
- title: "Maugli Rubrics Key Topics and Content Categories"
8
- description: "Explore Maugli Rubrics: curated topics and categories for those interested in AI, process automation, content marketing, and cutting-edge technologies."
9
- keywords: ["rubrics", "topics", "categories", "AI", "content automation", "content marketing"]
7
+ title: "Рубрики Maugli — ключевые темы и категории контента"
8
+ description: "Рубрики Maugli: от ИИ и автоматизации процессов до контент-маркетинга и GPT-SEO. Подборки по темам, основанные на реальных трендах и проверенных источниках."
9
+ keywords: ["рубрики", "теги", "темы", "категории", "ИИ", "AI", "автоматизация контента", "контент-маркетинг", "GPT-SEO", "Generated Engine Optimization"]
10
10
  jsonld:
11
11
  "@context": "https://schema.org"
12
12
  "@type": "CollectionPage"
13
- name: "Maugli Rubrics"
14
- url: "https://blog.maugli.cfd/en/rubrics"
15
- description: "Maugli Rubrics curated topics and categories with content focused on automation, AI, and business-driven strategies."
13
+ name: "Рубрики Maugli"
14
+ url: "https://blogru.maugli.cfd/tags"
15
+ description: "Подборки материалов по ключевым темам: ИИ, автоматизация, контент-стратегия, GPT-SEO и дистрибуция. Основано на реальных трендах и проверенных данных."
16
16
  publisher:
17
17
  "@type": "Organization"
18
- name: "Maugli Editorial Platform"
18
+ name: "Редакционная платформа Maugli"
19
19
  logo:
20
20
  "@type": "ImageObject"
21
- url: "https://blog.maugli.cfd/logoblog-icon.svg"
22
- inLanguage: "en"
21
+ url: "https://blogru.maugli.cfd/logoblog-icon.svg"
22
+ inLanguage: "ru"
23
23
  ---
24
24
 
25
+ Хотя контент **Maugli** — это демо-витрина, все рубрики и статьи собраны из **живых трендов, актуальных тем и проверенных источников**.
25
26
 
26
- Although **Maugli** content serves as a demo showcase, all rubrics and articles are based on **real trends, relevant topics, and verified data**.
27
+ Эта страница поможет понять, какие темы и направления мы освещаем, и быстро найти материалы по интересующим вопросам.:
28
+ - Хотите автоматизировать производство контента и маркетинговые процессы;
29
+ - Ищете рабочие способы встроить ИИ в свой пайплайн;
30
+ - Выстраиваете современную контент-стратегию, которая индексируется и людьми, и нейросетями.
27
31
 
28
- Our rubrics are designed for those who:
29
- - Want to automate their content and marketing workflows.
30
- - Seek powerful tools to integrate AI into their processes.
31
- - Are interested in modern content strategy practices.
32
+ Каждая рубрика это **структурированный пул материалов**, созданный на стыке **нейросетевой аналитики и редакторской экспертизы**: от практики GPT-SEO (Generated Engine Optimization) до дистрибуции по Telegram, Reddit, Medium и RSS.
32
33
 
33
- Each section offers structured and valuable content, created at the intersection of **neural networks and expert editorial insight**.
34
+ > «Рубрики Maugli помогают быстро находить то, что интересует.»
34
35
 
35
- > “Maugli Rubrics help you quickly find the content that truly works for your business.”
@@ -5,6 +5,9 @@ publishDate: 2024-01-01
5
5
  updatedDate: 2024-01-01
6
6
  isFeatured: false
7
7
  tags: ['demo', 'example']
8
+ image:
9
+ src: '/img/examples/projects/example_project.webp'
10
+ alt: 'Example Project Demo'
8
11
  seo:
9
12
  title: 'Example Project'
10
13
  description: 'Demo project for showcase purposes.'
@@ -3,6 +3,9 @@ title: Maugli Content Farms
3
3
  description: ИИ-редакция полного цикла для создания контента блогов, телеграм-каналов и соцсетей
4
4
  publishDate: '2025-05-11'
5
5
  tags: ['ИИ', 'Автоматизация', 'Контент', 'Мауgли']
6
+ image:
7
+ src: '/img/examples/projects/project_1.webp'
8
+ alt: 'Maugli Content Farms - ИИ-редакция полного цикла'
6
9
  productID: 'blackbox'
7
10
  productLink: 'https://google.com'
8
11
  generativeEngineOptimization:
package/src/i18n/en.json CHANGED
@@ -37,7 +37,7 @@
37
37
  "title": "Categories",
38
38
  "description": "All articles by category",
39
39
  "blogRubrics": "Blog categories",
40
- "moreTags": "More tags"
40
+ "moreTags": "Tags"
41
41
  },
42
42
  "index": {
43
43
  "title": "<Blog>",
package/src/i18n/es.json CHANGED
@@ -37,7 +37,7 @@
37
37
  "title": "Categorías",
38
38
  "description": "Todos los artículos por categoría",
39
39
  "blogRubrics": "Categorías del blog",
40
- "moreTags": "Más etiquetas"
40
+ "moreTags": "Etiquetas"
41
41
  },
42
42
  "index": {
43
43
  "title": "<Blog>",
@@ -106,7 +106,7 @@
106
106
  "tagsSection": {
107
107
  "allCases": "Todos los casos",
108
108
  "allArticles": "Todos los artículos",
109
- "allTags": "Todas las etiquetas",
109
+ "allTags": "Etiquetas",
110
110
  "rubricAlt": "Categoría",
111
111
  "tagAriaLabel": "Etiqueta: {name} ({count})"
112
112
  },
package/src/i18n/fr.json CHANGED
@@ -37,7 +37,7 @@
37
37
  "title": "Catégories",
38
38
  "description": "Tous les articles par catégorie",
39
39
  "blogRubrics": "Catégories du blog",
40
- "moreTags": "Plus de tags"
40
+ "moreTags": "Tags"
41
41
  },
42
42
  "index": {
43
43
  "title": "<Blog>",
@@ -106,7 +106,7 @@
106
106
  "tagsSection": {
107
107
  "allCases": "Tous les cas",
108
108
  "allArticles": "Tous les articles",
109
- "allTags": "Tous les tags",
109
+ "allTags": "Tags",
110
110
  "rubricAlt": "Catégorie",
111
111
  "tagAriaLabel": "Tag : {name} ({count})"
112
112
  },
package/src/i18n/ja.json CHANGED
@@ -37,7 +37,7 @@
37
37
  "title": "カテゴリ",
38
38
  "description": "カテゴリごとの記事一覧",
39
39
  "blogRubrics": "ブログカテゴリ",
40
- "moreTags": "その他のタグ"
40
+ "moreTags": "タグ"
41
41
  },
42
42
  "index": {
43
43
  "title": "<ブログ>",
package/src/i18n/zh.json CHANGED
@@ -37,7 +37,7 @@
37
37
  "title": "分类",
38
38
  "description": "按类别查看所有文章",
39
39
  "blogRubrics": "博客分类",
40
- "moreTags": "更多标签"
40
+ "moreTags": "标签"
41
41
  },
42
42
  "index": {
43
43
  "title": "<博客>",
@@ -1,6 +1,5 @@
1
1
  ---
2
2
  import { type CollectionEntry, render } from 'astro:content';
3
- import { getFilteredCollection } from '../../utils/content-loader';
4
3
  import ArticleMeta from '../../components/ArticleMeta.astro';
5
4
  import ContentFooter from '../../components/ContentFooter.astro';
6
5
  import HeroImage from '../../components/HeroImage.astro';
@@ -12,6 +11,7 @@ import TableOfContents from '../../components/TableOfContents.astro';
12
11
  import TagsAndShare from '../../components/TagsAndShare.astro';
13
12
  import { maugliConfig } from '../../config/maugli.config';
14
13
  import BaseLayout from '../../layouts/BaseLayout.astro';
14
+ import { getFilteredCollection } from '../../utils/content-loader';
15
15
  import { sortItemsByDateDesc } from '../../utils/data-utils';
16
16
  import { calculateReadingTime } from '../../utils/reading-time';
17
17
 
@@ -117,8 +117,9 @@ if (post.data.productID) {
117
117
  product={{
118
118
  data: {
119
119
  productLink: post.data.productLink,
120
- image: bannerImage,
121
- title: post.data.title || 'Продукт'
120
+ image: post.data.image || { src: maugliConfig.seo.defaultImage, alt: post.data.title || 'Продукт' },
121
+ title: post.data.title || 'Продукт',
122
+ productID: post.data.productID
122
123
  }
123
124
  }}
124
125
  />
@@ -105,11 +105,9 @@ const moreByTag = pages.projects?.moreByTag || 'More cases';
105
105
  product={{
106
106
  data: {
107
107
  productLink: project.data.productLink,
108
- image: {
109
- src: project.data.productID ? `/public/${project.data.productID}.webp` : maugliConfig.seo.defaultImage,
110
- alt: project.data.title || 'Продукт'
111
- },
112
- title: project.data.title || 'Продукт'
108
+ image: project.data.image || { src: maugliConfig.seo.defaultImage, alt: project.data.title || 'Продукт' },
109
+ title: project.data.title || 'Продукт',
110
+ productID: project.data.productID
113
111
  }
114
112
  }}
115
113
  />