iwgt 2.3.0

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.
@@ -0,0 +1,157 @@
1
+ /**
2
+ * Утилиты для работы с виджетами
3
+ * Модуль содержит вспомогательные функции
4
+ */
5
+ import blockTemplatesFull from '../data/references/block-templates-full.json' with { type: 'json' };
6
+ import categoryBlockTemplates from '../data/references/category-block-templates.json' with { type: 'json' };
7
+ /**
8
+ * Определить категорию виджета по описанию
9
+ */
10
+ export function inferCategory(description) {
11
+ const desc = description.toLowerCase();
12
+ // Словарь ключевых слов для категорий
13
+ const categoryKeywords = {
14
+ 'sliders': ['слайдер', 'slider', 'карусель', 'carousel', 'прокрутка'],
15
+ 'banner': ['баннер', 'banner', 'промо', 'promo'],
16
+ 'benefits': ['преимущества', 'benefits', 'плюсы', 'advantages'],
17
+ 'headers': ['шапка', 'header', 'хедер', 'шапка сайта', 'хедер сайта'],
18
+ 'footers': ['подвал', 'footer', 'футер'],
19
+ 'navigation': ['навигация', 'navigation', 'меню', 'menu'],
20
+ 'forms': ['форма', 'form', 'заявка', 'обратная связь'],
21
+ 'products-cards': ['карточка товара', 'product card', 'товар'],
22
+ 'collection-products': ['товары категории', 'collection products', 'каталог'],
23
+ 'product-homepage': ['товары на главной', 'products homepage', 'главная'],
24
+ 'cart': ['корзина', 'cart', 'basket'],
25
+ 'reviews': ['отзывы', 'reviews', 'отзыв'],
26
+ 'comments': ['комментарии', 'comments', 'комментарий'],
27
+ 'blog': ['блог', 'blog', 'статьи', 'articles'],
28
+ 'modals': ['модальное окно', 'modal', 'popup', 'всплывающее окно'],
29
+ 'text': ['текст', 'text', 'контент', 'content'],
30
+ 'video': ['видео', 'video'],
31
+ 'stories': ['истории', 'stories', 'сторис'],
32
+ 'filters': ['фильтры', 'filters', 'фильтр'],
33
+ 'search-results': ['поиск', 'search', 'результаты поиска'],
34
+ 'compare': ['сравнение', 'compare', 'сравнить'],
35
+ 'favorites': ['избранное', 'favorites', 'wishlist'],
36
+ 'recently-viewed': ['просмотренные', 'recently viewed', 'история'],
37
+ };
38
+ // Ищем совпадения
39
+ for (const [category, keywords] of Object.entries(categoryKeywords)) {
40
+ if (keywords.some(keyword => desc.includes(keyword))) {
41
+ return category;
42
+ }
43
+ }
44
+ // По умолчанию возвращаем 'drugie' (другие)
45
+ return 'drugie';
46
+ }
47
+ /**
48
+ * Определить тип виджета по описанию
49
+ */
50
+ export function inferType(description) {
51
+ const desc = description.toLowerCase();
52
+ // Ключевые слова, указывающие на BlockListWidgetType
53
+ const blockListKeywords = [
54
+ 'блоки', 'blocks', 'слайдер', 'slider', 'карусель', 'список',
55
+ 'несколько', 'multiple', 'коллекция', 'галерея', 'gallery',
56
+ ];
57
+ if (blockListKeywords.some(keyword => desc.includes(keyword))) {
58
+ return 'block_list_widget_type';
59
+ }
60
+ return 'simple_widget_type';
61
+ }
62
+ /**
63
+ * Сгенерировать handle виджета из описания
64
+ */
65
+ export function generateHandle(description) {
66
+ // Очищаем и нормализуем описание
67
+ let handle = description
68
+ .toLowerCase()
69
+ .trim()
70
+ .replace(/[^\wа-яё\s]/gi, '') // удаляем спецсимволы
71
+ .replace(/\s+/g, '_'); // заменяем пробелы на подчёркивания
72
+ // Транслитерация русских букв
73
+ const translitMap = {
74
+ 'а': 'a', 'б': 'b', 'в': 'v', 'г': 'g', 'д': 'd', 'е': 'e', 'ё': 'e',
75
+ 'ж': 'zh', 'з': 'z', 'и': 'i', 'й': 'y', 'к': 'k', 'л': 'l', 'м': 'm',
76
+ 'н': 'n', 'о': 'o', 'п': 'p', 'р': 'r', 'с': 's', 'т': 't', 'у': 'u',
77
+ 'ф': 'f', 'х': 'h', 'ц': 'ts', 'ч': 'ch', 'ш': 'sh', 'щ': 'sch',
78
+ 'ъ': '', 'ы': 'y', 'ь': '', 'э': 'e', 'ю': 'yu', 'я': 'ya',
79
+ };
80
+ handle = handle.replace(/[а-яё]/g, char => translitMap[char] || char);
81
+ // Ограничиваем длину (берём первые 5 слов)
82
+ const words = handle.split('_').filter(w => w.length > 0).slice(0, 5);
83
+ handle = words.join('_');
84
+ // Добавляем префикс v4_ если его нет
85
+ if (!handle.startsWith('v4_')) {
86
+ handle = 'v4_' + handle;
87
+ }
88
+ return handle;
89
+ }
90
+ /**
91
+ * Выбрать подходящий блок-темплейт
92
+ */
93
+ export function selectBlockTemplate(description, category) {
94
+ const desc = description.toLowerCase();
95
+ const fullData = blockTemplatesFull;
96
+ const allTemplates = fullData.templates || [];
97
+ // Получаем список темплейтов для категории
98
+ const categoryData = categoryBlockTemplates[category] || [];
99
+ const categoryHandles = categoryData.map((t) => t.handle);
100
+ if (categoryHandles.length === 0) {
101
+ // Если для категории нет специфичных темплейтов, используем универсальные
102
+ const template = allTemplates.find((t) => t.handle === 'system-banner-2' ||
103
+ t.handle === 'system-image-text-button-icon');
104
+ return template;
105
+ }
106
+ // Фильтруем темплейты по категории
107
+ const templates = allTemplates.filter((t) => categoryHandles.includes(t.handle));
108
+ if (templates.length === 0) {
109
+ return undefined;
110
+ }
111
+ // Пытаемся найти наиболее подходящий темплейт по ключевым словам
112
+ for (const template of templates) {
113
+ if (template.keywords) {
114
+ const hasMatch = template.keywords.some((keyword) => desc.includes(keyword.toLowerCase()));
115
+ if (hasMatch) {
116
+ return template;
117
+ }
118
+ }
119
+ }
120
+ // Если не нашли по ключевым словам, возвращаем первый из списка
121
+ return templates[0];
122
+ }
123
+ /**
124
+ * Валидация handle виджета
125
+ */
126
+ export function validateHandle(handle) {
127
+ // Не должен начинаться с system_
128
+ if (handle.startsWith('system_')) {
129
+ return {
130
+ valid: false,
131
+ error: 'Handle не может начинаться с "system_" - это зарезервировано для системных виджетов',
132
+ };
133
+ }
134
+ // Должен содержать только латинские буквы, цифры и подчёркивания
135
+ if (!/^[a-z0-9_]+$/.test(handle)) {
136
+ return {
137
+ valid: false,
138
+ error: 'Handle должен содержать только строчные латинские буквы, цифры и подчёркивания',
139
+ };
140
+ }
141
+ // Не должен быть слишком коротким
142
+ if (handle.length < 3) {
143
+ return {
144
+ valid: false,
145
+ error: 'Handle должен содержать минимум 3 символа',
146
+ };
147
+ }
148
+ // Не должен быть слишком длинным
149
+ if (handle.length > 50) {
150
+ return {
151
+ valid: false,
152
+ error: 'Handle не должен превышать 50 символов',
153
+ };
154
+ }
155
+ return { valid: true };
156
+ }
157
+ //# sourceMappingURL=index.js.map
package/package.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "iwgt",
3
+ "version": "2.3.0",
4
+ "description": "MCP server",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "iwgt": "dist/index.js",
9
+ "iwgt-http": "dist/server-http.js"
10
+ },
11
+ "keywords": [
12
+ "mcp",
13
+ "mcp-server"
14
+ ],
15
+ "author": "",
16
+ "license": "MIT",
17
+ "repository": {
18
+ "type": "git",
19
+ "url": ""
20
+ },
21
+ "engines": {
22
+ "node": ">=18.0.0"
23
+ },
24
+ "dependencies": {
25
+ "@modelcontextprotocol/sdk": "^1.0.4",
26
+ "zod": "^3.23.8"
27
+ }
28
+ }