core-maugli 1.0.2

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.
Files changed (206) hide show
  1. package/LICENSE +727 -0
  2. package/README.md +108 -0
  3. package/bin/index.js +9 -0
  4. package/bin/init.js +38 -0
  5. package/package.json +73 -0
  6. package/public/blackbox.webp +0 -0
  7. package/public/favicon.svg +10 -0
  8. package/public/footerlabel.svg +18 -0
  9. package/public/icon-192.png +0 -0
  10. package/public/icon-512.png +0 -0
  11. package/public/img/page-images/blog_default.webp +0 -0
  12. package/public/logo-icon.svg +3 -0
  13. package/public/logoblog-icon.svg +10 -0
  14. package/public/manifest.webmanifest +21 -0
  15. package/public/maugli_for_animation.svg +6 -0
  16. package/public/mauglilabel.svg +17 -0
  17. package/public/tr-about-1200.webp +0 -0
  18. package/public/tr-about-400.webp +0 -0
  19. package/public/tr-about-800.webp +0 -0
  20. package/public/tr-about.webp +0 -0
  21. package/public/tr-post-1-1200.webp +0 -0
  22. package/public/tr-post-1-400.webp +0 -0
  23. package/public/tr-post-1-800.webp +0 -0
  24. package/public/tr-post0-1200.webp +0 -0
  25. package/public/tr-post0-400.webp +0 -0
  26. package/public/tr-post0-800.webp +0 -0
  27. package/public/tr-post0.webp +0 -0
  28. package/public/tr-prewiew.webp +0 -0
  29. package/resize-all.cjs +29 -0
  30. package/scripts/featured.js +208 -0
  31. package/scripts/update-with-backup.js +34 -0
  32. package/scripts/upgrade-config.js +90 -0
  33. package/scripts/verify-assets.js +28 -0
  34. package/src/assets/img/default/autor_default.webp +0 -0
  35. package/src/assets/img/default/blog_default.webp +0 -0
  36. package/src/assets/img/default/product_default.webp +0 -0
  37. package/src/assets/img/default/project_default.webp +0 -0
  38. package/src/assets/img/default/rubric_default.webp +0 -0
  39. package/src/assets/img/examples/authors/anna.webp +0 -0
  40. package/src/assets/img/examples/authors/carlos.webp +0 -0
  41. package/src/assets/img/examples/authors/daria.webp +0 -0
  42. package/src/assets/img/examples/authors/dmitry.webp +0 -0
  43. package/src/assets/img/examples/authors/igor.webp +0 -0
  44. package/src/assets/img/examples/authors/john.webp +0 -0
  45. package/src/assets/img/examples/blog/post-1-avtomatizaciya-marketinga-kak-ii-osvobozhdaet-predprinimatelei-ot-cifrovogo-rabstva.webp +0 -0
  46. package/src/assets/img/examples/blog/post_11.webp +0 -0
  47. package/src/assets/img/examples/blog/post_12.webp +0 -0
  48. package/src/assets/img/examples/blog/post_1_jsonld_guide.webp +0 -0
  49. package/src/assets/img/examples/blog/test-post.webp +0 -0
  50. package/src/assets/img/examples/blog/tr-post-1.webp +0 -0
  51. package/src/assets/img/examples/products/product_1.webp +0 -0
  52. package/src/assets/img/examples/products/product_2.webp +0 -0
  53. package/src/assets/img/examples/projects/project_1.webp +0 -0
  54. package/src/assets/img/examples/projects/project_2.webp +0 -0
  55. package/src/components/ArticleMeta.astro +103 -0
  56. package/src/components/AuthorCard.astro +95 -0
  57. package/src/components/AuthorLink.astro +25 -0
  58. package/src/components/AuthorLinksGroup.astro +135 -0
  59. package/src/components/Avatar.astro +32 -0
  60. package/src/components/BaseHead.astro +121 -0
  61. package/src/components/Breadcrumbs.astro +90 -0
  62. package/src/components/Button.astro +25 -0
  63. package/src/components/Card.astro +99 -0
  64. package/src/components/ContentFooter.astro +147 -0
  65. package/src/components/CopyLinkButton.astro +133 -0
  66. package/src/components/CountBadge.astro +17 -0
  67. package/src/components/Footer.astro +122 -0
  68. package/src/components/FormattedDate.astro +59 -0
  69. package/src/components/Header.astro +18 -0
  70. package/src/components/HeroImage.astro +38 -0
  71. package/src/components/IconButton.astro +23 -0
  72. package/src/components/Image.astro +13 -0
  73. package/src/components/InfoCard.astro +123 -0
  74. package/src/components/LanguageSwitcher.astro +122 -0
  75. package/src/components/MaugliFloatingLabel.astro +454 -0
  76. package/src/components/MobileTagsAndShare.astro +71 -0
  77. package/src/components/Nav.astro +151 -0
  78. package/src/components/NavLink.astro +31 -0
  79. package/src/components/Pagination.astro +70 -0
  80. package/src/components/PostPreview.astro +22 -0
  81. package/src/components/ProductBannerCard.astro +47 -0
  82. package/src/components/ProductPreview.astro +21 -0
  83. package/src/components/ProjectPreview.astro +21 -0
  84. package/src/components/RubricCard.astro +142 -0
  85. package/src/components/ShareIcon.astro +93 -0
  86. package/src/components/ShareLink.astro +58 -0
  87. package/src/components/Subscribe.astro +68 -0
  88. package/src/components/SummaryFAQCard.astro +106 -0
  89. package/src/components/TableOfContents.astro +143 -0
  90. package/src/components/TagPill.astro +41 -0
  91. package/src/components/TagPills.astro +42 -0
  92. package/src/components/TagsAndShare.astro +379 -0
  93. package/src/components/TagsSection.astro +203 -0
  94. package/src/components/ThemeToggle.astro +58 -0
  95. package/src/config/maugli.config.ts +213 -0
  96. package/src/content/authors/daria-zorina.md +42 -0
  97. package/src/content/authors/default-autor.md +47 -0
  98. package/src/content/authors/igor-sokolov.md +43 -0
  99. package/src/content/authors/john-walker.md +46 -0
  100. package/src/content/blog/jsonld-guide.md +260 -0
  101. package/src/content/blog/post-0.md +49 -0
  102. package/src/content/blog/post-1-avtomatizaciya-marketinga-kak-ii-osvobozhdaet-predprinimatelei-ot-cifrovogo-rabstva.md +72 -0
  103. package/src/content/blog/post-agent-experience-mcp-biznes-v-epohu-ii-agentov.md +116 -0
  104. package/src/content/blog/test-post-2025-07-11.md +73 -0
  105. package/src/content/config.ts +80 -0
  106. package/src/content/pages/about.md +40 -0
  107. package/src/content/pages/about.mdx +27 -0
  108. package/src/content/pages/authors.mdx +49 -0
  109. package/src/content/pages/blog.mdx +31 -0
  110. package/src/content/pages/contact.md +10 -0
  111. package/src/content/pages/products.mdx +30 -0
  112. package/src/content/pages/projects.mdx +28 -0
  113. package/src/content/pages/rubrics.mdx +35 -0
  114. package/src/content/pages/terms.md +12 -0
  115. package/src/content/products/example-product.md +28 -0
  116. package/src/content/products/maugli-editor.md +35 -0
  117. package/src/content/products/maugli-freeblog.md +162 -0
  118. package/src/content/projects/example-project.md +28 -0
  119. package/src/content/projects/project-1.md +70 -0
  120. package/src/content/projects/project-2.md +33 -0
  121. package/src/content/tags/ai-business.mdx +18 -0
  122. package/src/content/tags/automation.mdx +18 -0
  123. package/src/content/tags/content-strategy.mdx +18 -0
  124. package/src/content/tags/growth-marketing.mdx +18 -0
  125. package/src/content/tags/industry-reviews.mdx +18 -0
  126. package/src/content/tags/interesting.mdx +18 -0
  127. package/src/content/tags/seo-ai-seo.mdx +18 -0
  128. package/src/content.config.ts +260 -0
  129. package/src/data/site-config.ts +164 -0
  130. package/src/i18n/de.json +126 -0
  131. package/src/i18n/en.json +126 -0
  132. package/src/i18n/es.json +126 -0
  133. package/src/i18n/fr.json +126 -0
  134. package/src/i18n/index.ts +10 -0
  135. package/src/i18n/ja.json +126 -0
  136. package/src/i18n/languages.ts +23 -0
  137. package/src/i18n/pt.json +126 -0
  138. package/src/i18n/ru.json +123 -0
  139. package/src/i18n/zh.json +126 -0
  140. package/src/icons/ArrowLeft.astro +13 -0
  141. package/src/icons/ArrowRight.astro +13 -0
  142. package/src/icons/flags/brazil.svg +14 -0
  143. package/src/icons/flags/china.svg +15 -0
  144. package/src/icons/flags/france.svg +12 -0
  145. package/src/icons/flags/germany.svg +12 -0
  146. package/src/icons/flags/japan.svg +11 -0
  147. package/src/icons/flags/russia.svg +12 -0
  148. package/src/icons/flags/spain.svg +12 -0
  149. package/src/icons/flags/united arab emirates.svg +13 -0
  150. package/src/icons/flags/united states.svg +15 -0
  151. package/src/icons/socials/BlueskyIcon.astro +9 -0
  152. package/src/icons/socials/EmailIcon.astro +8 -0
  153. package/src/icons/socials/LinkedinIcon.astro +9 -0
  154. package/src/icons/socials/MastodonIcon.astro +9 -0
  155. package/src/icons/socials/MediumIcon.astro +9 -0
  156. package/src/icons/socials/RedditIcon.astro +11 -0
  157. package/src/icons/socials/TelegramIcon.astro +11 -0
  158. package/src/icons/socials/TwitterIcon.astro +9 -0
  159. package/src/img/default/autor_default.webp +0 -0
  160. package/src/img/default/default.webp +0 -0
  161. package/src/img/default/rubric_default.webp +0 -0
  162. package/src/img/default/test.webp +0 -0
  163. package/src/img/default/test2.webp +0 -0
  164. package/src/img/examples/authors/anna.webp +0 -0
  165. package/src/img/examples/authors/carlos.webp +0 -0
  166. package/src/img/examples/authors/daria.webp +0 -0
  167. package/src/img/examples/authors/dmitry.webp +0 -0
  168. package/src/img/examples/authors/igor.webp +0 -0
  169. package/src/img/examples/authors/john.webp +0 -0
  170. package/src/img/examples/blog/post-1-avtomatizaciya-marketinga-kak-ii-osvobozhdaet-predprinimatelei-ot-cifrovogo-rabstva.webp +0 -0
  171. package/src/img/examples/blog/post-2-avtomatizaciya-kontenta-kak-neiroseti-ubivayut-perfekcionizm-v-biznese.webp +0 -0
  172. package/src/img/examples/blog/post-3-laik-ne-valyuta-kak-avtomatizaciya-marketinga-spasaet-ot-lozhnyh-metrik.webp +0 -0
  173. package/src/img/examples/blog/post-5-5-fatalnyh-oshibok-marketinga-kotorye-ubivayut-startapy-na-starte.webp +0 -0
  174. package/src/img/examples/blog/post-6-5-strategii-kontent-marketinga-dlya-startapov-avtomatizaciya-i-revolyuciya.webp +0 -0
  175. package/src/img/examples/blog/post-7-viralnyi-kontent-ne-udacha-a-strategiya-avtomatizaciya-marketinga.webp +0 -0
  176. package/src/img/examples/blog/post-agent-experience-mcp-biznes-v-epohu-ii-agentov.webp +0 -0
  177. package/src/img/examples/blog/post_1_jsonld_guide.webp +0 -0
  178. package/src/img/examples/blog/tr-post-1.webp +0 -0
  179. package/src/layouts/BaseLayout.astro +59 -0
  180. package/src/pages/404.astro +24 -0
  181. package/src/pages/[...id].astro +50 -0
  182. package/src/pages/about.astro +0 -0
  183. package/src/pages/authors/[...page].astro +105 -0
  184. package/src/pages/authors/[id].astro +165 -0
  185. package/src/pages/blog/[...page].astro +59 -0
  186. package/src/pages/blog/[id].astro +175 -0
  187. package/src/pages/index.astro +90 -0
  188. package/src/pages/products/[...page].astro +50 -0
  189. package/src/pages/products/[id].astro +221 -0
  190. package/src/pages/projects/[...page].astro +74 -0
  191. package/src/pages/projects/[id].astro +165 -0
  192. package/src/pages/projects/tags/[id]/[...page].astro +58 -0
  193. package/src/pages/rss.xml.js +5 -0
  194. package/src/pages/tags/[id]/[...page].astro +110 -0
  195. package/src/pages/tags/index.astro +124 -0
  196. package/src/scripts/infoCardFadeIn.js +22 -0
  197. package/src/styles/global.css +272 -0
  198. package/src/utils/common-utils.ts +0 -0
  199. package/src/utils/content-loader.ts +14 -0
  200. package/src/utils/data-utils.ts +49 -0
  201. package/src/utils/featuredManager.ts +118 -0
  202. package/src/utils/posts.ts +43 -0
  203. package/src/utils/reading-time.ts +28 -0
  204. package/src/utils/remark-slugify.js +8 -0
  205. package/src/utils/rss.ts +23 -0
  206. package/typograf-batch.js +49 -0
@@ -0,0 +1,123 @@
1
+ ---
2
+
3
+ /**
4
+ * @typedef InfoCardProps
5
+ * @property {string} [title]
6
+ * @property {string} [description]
7
+ * @property {{ src: string, alt?: string }} [image]
8
+ * @property {string} [class]
9
+ * @property {any} [jsonld]
10
+ */
11
+
12
+
13
+ import { marked } from 'marked';
14
+ /** @type {InfoCardProps} */
15
+ const { title, description = '', class: className = '', jsonld } = Astro.props;
16
+ let html = description ? marked.parse(description) : '';
17
+ ---
18
+
19
+ {
20
+ description && (
21
+ <>
22
+ <div class={`w-full max-w-full rounded-custom px-8 py-8 mb-8 card-bg grid grid-cols-1 sm:grid-cols-16 items-start ${className}`}>
23
+ <div class="sm:col-span-5 flex items-start justify-start mb-4 sm:mb-0">
24
+ {title && (
25
+ <h2 class="text-3xl sm:text-4xl sm:mt-3 ld:mt-8 font-serif font-extrabold leading-tight line-clamp-3" style="color: var(--text-heading);">
26
+ {title}
27
+ </h2>
28
+ )}
29
+ </div>
30
+ <div class="sm:col-span-11 mt-0 text-m sm:text-m info-card-content prose" style="color: var(--text-main); opacity: 0.8;">
31
+ <div set:html={html} />
32
+ </div>
33
+ </div>
34
+ {jsonld && (
35
+ <script type="application/ld+json">
36
+ {JSON.stringify(jsonld)}
37
+ </script>
38
+ )}
39
+ </>
40
+ )
41
+ }
42
+
43
+ <style>
44
+ .info-card-content :global(h3) {
45
+ font-family: var(--font-serif);
46
+ font-weight: var(--font-weight-extra-bold, 800);
47
+ font-size: 1.5rem;
48
+ margin-top: 1.5rem;
49
+ margin-bottom: 0.75rem;
50
+ color: var(--text-heading);
51
+ line-height: 1.05;
52
+ }
53
+ .info-card-content :global(p) {
54
+ font-family: var(--font-sans);
55
+ margin-bottom: 1rem;
56
+ font-size: 1rem;
57
+ line-height: 1.4;
58
+ color: var(--text-main);
59
+ }
60
+ .info-card-content :global(ul),
61
+ .info-card-content :global(ol) {
62
+ margin-left: 1.5rem;
63
+ margin-bottom: 1rem;
64
+ padding-left: 1.2rem;
65
+ line-height: 1.4;
66
+ color: var(--text-main);
67
+ list-style-position: inside;
68
+ }
69
+ .info-card-content :global(ul) {
70
+ list-style-type: disc;
71
+ }
72
+ .info-card-content :global(ol) {
73
+ list-style-type: decimal;
74
+ }
75
+ .info-card-content :global(ul ul),
76
+ .info-card-content :global(ol ul),
77
+ .info-card-content :global(ul ol),
78
+ .info-card-content :global(ol ol) {
79
+ margin-top: 0.5rem;
80
+ margin-bottom: 0.5rem;
81
+ margin-left: 1.2rem;
82
+ font-size: 0.95em;
83
+ opacity: 0.85;
84
+ }
85
+ .info-card-content :global(li) {
86
+ font-family: var(--font-sans);
87
+ margin-bottom: 0.5rem;
88
+ font-size: 1rem;
89
+ line-height: 1.4;
90
+ color: var(--text-main);
91
+ padding-left: 0.2em;
92
+ }
93
+ .info-card-content :global(blockquote) {
94
+ font-family: var(--font-serif);
95
+ background: var(--bg-muted);
96
+ border-radius: var(--card-radius);
97
+ border-left: 1px solid var(--text-heading);
98
+ font-size: 1.3em;
99
+ padding: 1.2em 1em 1.2em 2.5em;
100
+ margin: 1.2rem 0;
101
+ color: rgba(var(--text-main));
102
+ box-shadow: none;
103
+ font-style: normal;
104
+ line-height: 1.2;
105
+ }
106
+ .info-card-content :global(a) {
107
+ color: var(--color-brand);
108
+ text-decoration: none;
109
+ transition: color 0.2s;
110
+ }
111
+ .info-card-content :global(a):hover {
112
+ color: var(--color-brand-60);
113
+ text-decoration: underline;
114
+ }
115
+ .info-card-content :global(code) {
116
+ background: var(--bg-muted);
117
+ padding: 0.2em 0.4em;
118
+ border-radius: var(--code-radius, 4px);
119
+ font-size: 0.95em;
120
+ font-family: var(--font-mono, 'Fira Mono', 'Consolas', monospace);
121
+ color: var(--text-main);
122
+ }
123
+ </style>
@@ -0,0 +1,122 @@
1
+ ---
2
+ import { LANGUAGES } from '../i18n/languages';
3
+ import { maugliConfig } from '../config/maugli.config';
4
+
5
+ const langLinks = maugliConfig.langLinks || {};
6
+ // Универсальный список языков: только те, что есть в langLinks и в LANGUAGES
7
+ const availableLanguages = LANGUAGES.filter((l) => langLinks[l.code]);
8
+ const currentLang = maugliConfig.defaultLang;
9
+ const showLangSwitcher = maugliConfig.showLangSwitcher !== false && availableLanguages.length > 1;
10
+ const current = availableLanguages.find((l) => l.code === currentLang) || availableLanguages[0];
11
+ ---
12
+
13
+ {
14
+ showLangSwitcher && (
15
+ <div class="relative inline-block text-left">
16
+ <button
17
+ id="lang-switcher"
18
+ class="flex items-center gap-2 px-4 py-2 rounded-[var(--radius-main)] bg-[var(--bg-main)] text-[var(--text-heading)] border-none cursor-pointer"
19
+ aria-haspopup="listbox"
20
+ aria-expanded="false"
21
+ style="width: auto; white-space: nowrap; height:48px; min-height:48px;"
22
+ >
23
+ <span
24
+ class="flag-box flex items-center justify-center w-7 h-7 rounded-[var(--radius-main)] shadow-[var(--shadow-main)]"
25
+ style="min-width:28px; min-height:28px; max-width:28px; max-height:28px;"
26
+ >
27
+ {current && (
28
+ <img
29
+ src={current.icon.replace(/^\/public\/|^\/|^flags\//, '/src/icons/flags/')}
30
+ alt={current.code.toUpperCase()}
31
+ width="28"
32
+ height="28"
33
+ style="pointer-events:none;"
34
+ />
35
+ )}
36
+ </span>
37
+ <svg class="w-4 h-4" viewBox="0 0 20 20" fill="currentColor">
38
+ <path
39
+ fill-rule="evenodd"
40
+ d="M5.23 7.21a.75.75 0 011.06.02L10 10.94l3.71-3.71a.75.75 0 111.06 1.06l-4.24 4.24a.75.75 0 01-1.06 0L5.21 8.29a.75.75 0 01.02-1.08z"
41
+ clip-rule="evenodd"
42
+ />
43
+ </svg>
44
+ </button>
45
+ <ul
46
+ id="lang-list"
47
+ class="absolute right-0 mt-2 px-3 py-4 rounded-[var(--rounded-custom)] bg-[var(--bg-muted)] shadow-[var(--shadow-main)] z-50 hidden"
48
+ role="listbox"
49
+ style="width: auto; min-width: max-content; white-space: nowrap;"
50
+ >
51
+ {availableLanguages.map((lang) => (
52
+ <li
53
+ class={`flex items-center rounded-[var(--radius-main)] gap-3 px-2 py-1 cursor-pointer hover:bg-[var(--bg-accent)] h-12 min-h-[48px] max-h-[48px] ${lang.code === currentLang ? 'font-bold text-[var(--brand-color)]' : ''}`}
54
+ data-lang={lang.code}
55
+ role="option"
56
+ aria-selected={lang.code === currentLang}
57
+ >
58
+ <a
59
+ href={langLinks[lang.code]}
60
+ target="_self"
61
+ class="flex items-center gap-2 w-full h-full"
62
+ style="text-decoration:none; color:inherit;"
63
+ >
64
+ <span
65
+ class="flag-box flex items-center justify-center w-7 h-7 rounded-[var(--radius-main)] shadow-[var(--shadow-main)]"
66
+ style="min-width:28px; min-height:28px; max-width:28px; max-height:28px;"
67
+ >
68
+ <img
69
+ src={lang.icon.replace(/^\/public\/|^\/|^flags\//, '/src/icons/flags/')}
70
+ alt={lang.code.toUpperCase()}
71
+ width="28"
72
+ height="28"
73
+ style="pointer-events:none;"
74
+ />
75
+ </span>
76
+ <span class="text-heading">{lang.label}</span>
77
+ </a>
78
+ </li>
79
+ ))}
80
+ </ul>
81
+ </div>
82
+ )
83
+ }
84
+
85
+ <script>
86
+ document.addEventListener('astro:page-load', () => {
87
+ const btn = document.getElementById('lang-switcher');
88
+ const list = document.getElementById('lang-list');
89
+ if (!btn || !list) return;
90
+ btn.addEventListener('click', () => {
91
+ const expanded = btn.getAttribute('aria-expanded') === 'true';
92
+ btn.setAttribute('aria-expanded', !expanded);
93
+ list.classList.toggle('hidden');
94
+ });
95
+ // Удаляем обработчики смены языка, теперь переход по ссылке
96
+ document.addEventListener('click', (e) => {
97
+ if (!btn.contains(e.target) && !list.contains(e.target)) {
98
+ btn.setAttribute('aria-expanded', false);
99
+ list.classList.add('hidden');
100
+ }
101
+ });
102
+ window.addEventListener('scroll', () => {
103
+ btn.setAttribute('aria-expanded', false);
104
+ list.classList.add('hidden');
105
+ });
106
+ });
107
+ </script>
108
+
109
+ <style>
110
+ #lang-list li[aria-selected='true'] {
111
+ background: transparent;
112
+ color: var(--brand-color);
113
+ border-radius: var(--rounded-custom);
114
+ font-weight: bold;
115
+ }
116
+ #lang-list li:hover {
117
+ background: var(--background-color-main);
118
+ border-radius: var(--rounded-custom);
119
+ color: var(--text-main);
120
+ font-weight: normal;
121
+ }
122
+ </style>