core-maugli 1.2.75 → 1.2.77

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/netlify.toml CHANGED
@@ -9,7 +9,7 @@
9
9
 
10
10
  [build]
11
11
  publish = "dist"
12
- command = "npm run build"
12
+ command = "npm update core-maugli && npm run build"
13
13
 
14
14
  [build.environment]
15
15
  NODE_VERSION = "20"
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.75",
5
+ "version": "1.2.77",
6
6
  "license": "GPL-3.0-or-later OR Commercial",
7
7
  "repository": {
8
8
  "type": "git",
File without changes
File without changes
File without changes
@@ -58,7 +58,12 @@ const REQUIRED_SCRIPTS = [
58
58
  'scripts/check-version.js',
59
59
  'scripts/auto-update.js',
60
60
  'scripts/set-force-update.js',
61
- '.gitignore'
61
+ '.gitignore',
62
+ ];
63
+
64
+ // Файлы, которые должны быть в корне проекта
65
+ const REQUIRED_ROOT_FILES = [
66
+ 'astro-image-resize.mjs'
62
67
  ];
63
68
 
64
69
  function log(message, type = 'info') {
@@ -123,31 +128,43 @@ function updateBlogProject(projectPath) {
123
128
  // 5. Save package.json
124
129
  fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 4));
125
130
 
126
- // 6. Copy missing scripts
131
+ // 6. Copy scripts (заменяем всегда)
127
132
  const scriptsDir = path.join(absolutePath, 'scripts');
128
133
  if (!fs.existsSync(scriptsDir)) {
129
134
  fs.mkdirSync(scriptsDir, { recursive: true });
130
135
  }
131
-
132
136
  let scriptsCopied = 0;
133
- const sourceScriptsDir = path.join(process.cwd(), 'scripts');
134
-
135
137
  for (const scriptFile of REQUIRED_SCRIPTS) {
136
138
  const sourcePath = path.join(process.cwd(), scriptFile);
137
139
  const targetPath = path.join(absolutePath, scriptFile);
138
-
139
140
  if (fs.existsSync(sourcePath)) {
140
- // Создаем директорию если не существует
141
141
  const targetDir = path.dirname(targetPath);
142
142
  if (!fs.existsSync(targetDir)) {
143
143
  fs.mkdirSync(targetDir, { recursive: true });
144
144
  }
145
-
146
- // Копируем файл
145
+ // Всегда заменяем файл
147
146
  fs.copyFileSync(sourcePath, targetPath);
148
147
  scriptsCopied++;
149
148
  }
150
149
  }
150
+ // 6.1. Копируем файлы в корень (например, astro-image-resize.mjs)
151
+ for (const rootFile of REQUIRED_ROOT_FILES) {
152
+ const sourcePath = path.join(process.cwd(), rootFile);
153
+ const targetPath = path.join(absolutePath, rootFile);
154
+ if (fs.existsSync(sourcePath)) {
155
+ fs.copyFileSync(sourcePath, targetPath);
156
+ }
157
+ }
158
+ // 6.2. Удаляем дублирующиеся скрипты с " 2" в имени
159
+ const glob = require('glob');
160
+ const dups = glob.sync(path.join(scriptsDir, '* 2.*'));
161
+ for (const dup of dups) {
162
+ try {
163
+ fs.unlinkSync(dup);
164
+ } catch (e) {
165
+ log(`Не удалось удалить дубликат: ${dup}`, 'warning');
166
+ }
167
+ }
151
168
 
152
169
  // 7. Обновляем npm пакеты
153
170
  log(`Updating npm packages...`, 'info');
@@ -47,10 +47,17 @@ const faqCard = (dict as any).faqCard || (fallbackDict as any).faqCard || {};
47
47
  </div>
48
48
  <div class="flex-1 min-w-0 flex flex-col gap-4">
49
49
  {
50
- faq.map(({ question, answer }) => (
50
+ faq.map(({ question, answer }, idx) => (
51
51
  <div>
52
- <div class="font-sans text-[16px] text-[var(--text-heading)] mb-1 flex items-center">
53
- <span class="mr-2 flex-shrink-0">
52
+ <button
53
+ type="button"
54
+ class="font-sans text-[16px] text-[var(--text-heading)] mb-1 flex items-center w-full text-left group"
55
+ aria-expanded={idx === 0 ? 'true' : 'false'}
56
+ aria-controls={`faq-answer-${idx}`}
57
+ data-faq-idx={idx}
58
+ style="background:none;border:none;padding:0;outline:none;cursor:pointer;"
59
+ >
60
+ <span class="mr-2 flex-shrink-0 transition-transform duration-200 faq-chevron" style={idx === 0 ? 'transform:rotate(90deg);' : ''}>
54
61
  <svg width="16" height="16" viewBox="0 0 25 25" fill="none" xmlns="http://www.w3.org/2000/svg">
55
62
  <g clip-path="url(#clip0_3491_12515)">
56
63
  <path
@@ -68,11 +75,52 @@ const faqCard = (dict as any).faqCard || (fallbackDict as any).faqCard || {};
68
75
  </svg>
69
76
  </span>
70
77
  {question}
78
+ </button>
79
+ <div id={`faq-answer-${idx}`} class={`font-sans text-[14px] text-[var(--text-main)] ml-6 faq-answer${idx === 0 ? ' open' : ''}`}>
80
+ {answer}
71
81
  </div>
72
- <div class="font-sans text-[14px] text-[var(--text-main)] ml-6">{answer}</div>
73
82
  </div>
74
83
  ))
75
84
  }
76
85
  </div>
77
86
  </div>
78
87
  </section>
88
+
89
+ <style>
90
+ .faq-answer {
91
+ max-height: 0;
92
+ opacity: 0;
93
+ overflow: hidden;
94
+ transition:
95
+ max-height 0.35s cubic-bezier(0.4, 0, 0.2, 1),
96
+ opacity 0.25s cubic-bezier(0.4, 0, 0.2, 1);
97
+ will-change: max-height, opacity;
98
+ }
99
+ .faq-answer.open {
100
+ max-height: 500px;
101
+ opacity: 1;
102
+ }
103
+ </style>
104
+
105
+ <script>
106
+ // Плавный аккордеон без изменения дизайна
107
+ if (typeof window !== 'undefined') {
108
+ document.addEventListener('DOMContentLoaded', function () {
109
+ const buttons = document.querySelectorAll('[data-faq-idx]');
110
+ const answers = document.querySelectorAll('.faq-answer');
111
+ const chevrons = document.querySelectorAll('.faq-chevron');
112
+ buttons.forEach((btn, idx) => {
113
+ btn.addEventListener('click', function () {
114
+ buttons.forEach((b, i) => {
115
+ b.setAttribute('aria-expanded', 'false');
116
+ answers[i].classList.remove('open');
117
+ chevrons[i].style.transform = '';
118
+ });
119
+ btn.setAttribute('aria-expanded', 'true');
120
+ answers[idx].classList.add('open');
121
+ chevrons[idx].style.transform = 'rotate(90deg)';
122
+ });
123
+ });
124
+ });
125
+ }
126
+ </script>
@@ -156,8 +156,7 @@ if (post.data.productID) {
156
156
 
157
157
  <!-- FAQ после контента -->
158
158
  {
159
- post.data.generativeEngineOptimization?.generated?.faq &&
160
- post.data.generativeEngineOptimization.generated.faq.length > 0 && (
159
+ post.data.generativeEngineOptimization?.generated?.faq && post.data.generativeEngineOptimization.generated.faq.length > 0 && (
161
160
  <div class="not-prose mb-8">
162
161
  <FAQCard faq={post.data.generativeEngineOptimization.generated.faq} />
163
162
  </div>
@@ -1,6 +1,5 @@
1
1
  ---
2
2
  import { render, type CollectionEntry } from 'astro:content';
3
- import { getFilteredCollection } from '../../utils/content-loader';
4
3
  import ArticleMeta from '../../components/ArticleMeta.astro';
5
4
  import Breadcrumbs from '../../components/Breadcrumbs.astro';
6
5
  import ContentFooter from '../../components/ContentFooter.astro';
@@ -14,6 +13,7 @@ import TagsAndShare from '../../components/TagsAndShare.astro';
14
13
  import { maugliConfig } from '../../config/maugli.config';
15
14
  import { LANGUAGES } from '../../i18n/languages';
16
15
  import BaseLayout from '../../layouts/BaseLayout.astro';
16
+ import { getFilteredCollection } from '../../utils/content-loader';
17
17
  import { sortItemsByDateDesc } from '../../utils/data-utils';
18
18
  import { calculateReadingTime } from '../../utils/reading-time';
19
19
 
@@ -115,17 +115,16 @@ const moreLabel = dict.buttons?.more || dicts['en'].buttons.more || 'More';
115
115
  <div class="prose sm:prose-lg lg:prose-xl max-w-none">
116
116
  <Content />
117
117
  </div>
118
-
118
+
119
119
  {/* FAQ после контента продукта */}
120
120
  {
121
- product.data.generativeEngineOptimization?.generated?.faq &&
122
- product.data.generativeEngineOptimization.generated.faq.length > 0 && (
121
+ product.data.generativeEngineOptimization?.generated?.faq && product.data.generativeEngineOptimization.generated.faq.length > 0 && (
123
122
  <div class="not-prose mb-8">
124
123
  <FAQCard faq={product.data.generativeEngineOptimization.generated.faq} />
125
124
  </div>
126
125
  )
127
126
  }
128
-
127
+
129
128
  <ContentFooter tags={tags} shareUrl={href} title={title} basePath="/products" />
130
129
  {/* Связанные статьи */}
131
130
  {
@@ -146,8 +146,7 @@ const moreByTag = pages.projects?.moreByTag || 'More cases';
146
146
 
147
147
  <!-- FAQ после контента -->
148
148
  {
149
- project.data.generativeEngineOptimization?.generated?.faq &&
150
- project.data.generativeEngineOptimization.generated.faq.length > 0 && (
149
+ project.data.generativeEngineOptimization?.generated?.faq && project.data.generativeEngineOptimization.generated.faq.length > 0 && (
151
150
  <div class="not-prose mb-8">
152
151
  <FAQCard faq={project.data.generativeEngineOptimization.generated.faq} />
153
152
  </div>
package/src/pwa.ts ADDED
File without changes