@maxisoft/instantcms-mcp 1.2.3

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 (111) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +308 -0
  3. package/dist/__tests__/artifact-tool.test.js +196 -0
  4. package/dist/__tests__/db-tool.test.js +152 -0
  5. package/dist/__tests__/define-tool.test.js +106 -0
  6. package/dist/__tests__/find-tool.test.js +185 -0
  7. package/dist/__tests__/get-component-api.test.js +144 -0
  8. package/dist/__tests__/hardening.test.js +73 -0
  9. package/dist/__tests__/hooks-tool.test.js +173 -0
  10. package/dist/__tests__/mcp-integration-extra.test.js +166 -0
  11. package/dist/__tests__/mcp-integration.test.js +53 -0
  12. package/dist/__tests__/pagination.test.js +114 -0
  13. package/dist/__tests__/performance-baseline.test.js +56 -0
  14. package/dist/__tests__/project-patch.test.js +144 -0
  15. package/dist/__tests__/project-source.test.js +44 -0
  16. package/dist/__tests__/project-workflows-extra.test.js +165 -0
  17. package/dist/__tests__/project-workflows.test.js +51 -0
  18. package/dist/__tests__/scaffold-addon-roundtrip.test.js +287 -0
  19. package/dist/__tests__/serialization.test.js +170 -0
  20. package/dist/__tests__/source-knowledge-parsers.test.js +42 -0
  21. package/dist/__tests__/template-development.test.js +78 -0
  22. package/dist/__tests__/template-productivity.test.js +87 -0
  23. package/dist/__tests__/tools.test.js +2143 -0
  24. package/dist/data/components.js +2818 -0
  25. package/dist/data/controllers-map.js +7571 -0
  26. package/dist/data/core-api.js +9356 -0
  27. package/dist/data/database-schema.js +4555 -0
  28. package/dist/data/events-map.js +1339 -0
  29. package/dist/data/fields-map.js +3692 -0
  30. package/dist/data/hooks.js +2257 -0
  31. package/dist/data/js-api.js +123 -0
  32. package/dist/data/libs-api.js +264 -0
  33. package/dist/data/routes-map.js +203 -0
  34. package/dist/data/schemas-validation.js +255 -0
  35. package/dist/data/schemas.js +1404 -0
  36. package/dist/data/traits-map.js +1004 -0
  37. package/dist/data/version-profiles.js +41 -0
  38. package/dist/data/widgets-map.js +131 -0
  39. package/dist/data/wysiwyg-map.js +486 -0
  40. package/dist/generated/components-source.js +14748 -0
  41. package/dist/generated/hooks-source.js +3399 -0
  42. package/dist/generated/knowledge-meta.js +101 -0
  43. package/dist/index.js +13 -0
  44. package/dist/registry/database-tools.js +112 -0
  45. package/dist/registry/extension-tools.js +473 -0
  46. package/dist/registry/generator-tools.js +506 -0
  47. package/dist/registry/knowledge-tools.js +441 -0
  48. package/dist/registry/language-tools.js +99 -0
  49. package/dist/registry/meta-tools.js +152 -0
  50. package/dist/registry/project-tools.js +48 -0
  51. package/dist/registry/resources.js +98 -0
  52. package/dist/registry/source-tools.js +211 -0
  53. package/dist/registry/template-development-tools.js +79 -0
  54. package/dist/server.js +32 -0
  55. package/dist/tools/addon-tool.js +1437 -0
  56. package/dist/tools/admin-partial-tool.js +498 -0
  57. package/dist/tools/api-tool.js +294 -0
  58. package/dist/tools/artifact-tool.js +95 -0
  59. package/dist/tools/cache-tool.js +360 -0
  60. package/dist/tools/component-tool.js +415 -0
  61. package/dist/tools/controllers-tool.js +125 -0
  62. package/dist/tools/cron-tool.js +197 -0
  63. package/dist/tools/crud-tool.js +659 -0
  64. package/dist/tools/db-tool.js +198 -0
  65. package/dist/tools/email-tool.js +222 -0
  66. package/dist/tools/external-api-tool.js +596 -0
  67. package/dist/tools/filter-tool.js +341 -0
  68. package/dist/tools/form-tool.js +275 -0
  69. package/dist/tools/grid-tool.js +189 -0
  70. package/dist/tools/hooks-tool.js +104 -0
  71. package/dist/tools/import-export-tool.js +548 -0
  72. package/dist/tools/lang-tool.js +251 -0
  73. package/dist/tools/layout-override-tool.js +125 -0
  74. package/dist/tools/layout-tool.js +548 -0
  75. package/dist/tools/maria-tool.js +127 -0
  76. package/dist/tools/mariadb.js +201 -0
  77. package/dist/tools/migration-tool.js +329 -0
  78. package/dist/tools/oauth-tool.js +520 -0
  79. package/dist/tools/parser/components-parser.js +76 -0
  80. package/dist/tools/parser/controllers-parser.js +313 -0
  81. package/dist/tools/parser/core-parser.js +294 -0
  82. package/dist/tools/parser/coverage-generator.js +424 -0
  83. package/dist/tools/parser/events-parser.js +127 -0
  84. package/dist/tools/parser/fields-parser.js +382 -0
  85. package/dist/tools/parser/hooks-parser.js +106 -0
  86. package/dist/tools/parser/sql-parser.js +197 -0
  87. package/dist/tools/parser/traits-parser.js +161 -0
  88. package/dist/tools/parser/widgets-parser.js +150 -0
  89. package/dist/tools/permission-tool.js +348 -0
  90. package/dist/tools/project-patch-tool.js +73 -0
  91. package/dist/tools/project-source-tool.js +188 -0
  92. package/dist/tools/project-workflow-tool.js +186 -0
  93. package/dist/tools/requirement-tool.js +212 -0
  94. package/dist/tools/scaffold-tool.js +815 -0
  95. package/dist/tools/seo-tool.js +412 -0
  96. package/dist/tools/source-tool.js +155 -0
  97. package/dist/tools/template-development-tool.js +271 -0
  98. package/dist/tools/template-overrides-tool.js +294 -0
  99. package/dist/tools/template-productivity-tool.js +319 -0
  100. package/dist/tools/template-tool.js +665 -0
  101. package/dist/tools/test-tool.js +183 -0
  102. package/dist/tools/webhook-tool.js +427 -0
  103. package/dist/tools/widget-tool.js +331 -0
  104. package/dist/tools/wysiwyg-tool.js +137 -0
  105. package/dist/types/scaffold.js +68 -0
  106. package/dist/utils/define-tool.js +37 -0
  107. package/dist/utils/find-tool.js +97 -0
  108. package/dist/utils/mcp-result.js +18 -0
  109. package/dist/utils/pagination.js +27 -0
  110. package/dist/utils/serialization.js +27 -0
  111. package/package.json +94 -0
@@ -0,0 +1,498 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.scaffoldAdminPartial = scaffoldAdminPartial;
4
+ function scaffoldAdminPartial(opts) {
5
+ const name = opts.addon_name.toLowerCase().replace(/[^a-z0-9_]/g, '_');
6
+ const Name = name.split('_').map(capitalize).join('');
7
+ const NAME = name.toUpperCase();
8
+ const files = {};
9
+ for (const partial of opts.partials) {
10
+ const partialFileName = `${partial.type}_${partial.name}.php`;
11
+ files[`package/templates/admincoreui/partials/${name}/${partialFileName}`] = generatePartial(name, Name, NAME, partial, opts.options);
12
+ }
13
+ files[`package/templates/admincoreui/partials/${name}/${name}.php`] = generateIndexPartial(name, Name, NAME, opts.partials);
14
+ return {
15
+ addon_name: name,
16
+ partials_count: opts.partials.length,
17
+ files,
18
+ partials: opts.partials.map(p => ({
19
+ name: p.name,
20
+ type: p.type,
21
+ file: `${p.type}_${p.name}.php`,
22
+ })),
23
+ structure_notes: [
24
+ `Части админки: package/templates/admincoreui/partials/${name}/`,
25
+ `Использование в шаблоне: $this->renderPartial('${name}', '${name}_header', $vars)`,
26
+ `Или виджетом: <?php echo $this->widgets('admin_${name}_header'); ?>`,
27
+ ],
28
+ };
29
+ }
30
+ function capitalize(str) {
31
+ return str.charAt(0).toUpperCase() + str.slice(1);
32
+ }
33
+ function generatePartial(name, Name, NAME, partial, options) {
34
+ const useBootstrap = options?.use_bootstrap ?? true;
35
+ const useIcmsIcons = options?.use_icms_icons ?? true;
36
+ const iconSet = useIcmsIcons ? 'icon-' : 'fa fa-';
37
+ switch (partial.type) {
38
+ case 'header':
39
+ return generateHeaderPartial(name, Name, NAME, partial, useBootstrap, iconSet);
40
+ case 'sidebar':
41
+ return generateSidebarPartial(name, Name, NAME, partial, useBootstrap, iconSet);
42
+ case 'footer':
43
+ return generateFooterPartial(name, Name, NAME, partial, useBootstrap, iconSet);
44
+ case 'toolbar':
45
+ return generateToolbarPartial(name, Name, NAME, partial, useBootstrap, iconSet);
46
+ case 'breadcrumb':
47
+ return generateBreadcrumbPartial(name, Name, NAME, partial, useBootstrap, iconSet);
48
+ case 'panel':
49
+ return generatePanelPartial(name, Name, NAME, partial, useBootstrap, iconSet);
50
+ case 'modal':
51
+ return generateModalPartial(name, Name, NAME, partial, useBootstrap, iconSet);
52
+ case 'notification':
53
+ return generateNotificationPartial(name, Name, NAME, partial, useBootstrap, iconSet);
54
+ default:
55
+ return generateGenericPartial(name, Name, NAME, partial, useBootstrap, iconSet);
56
+ }
57
+ }
58
+ function generateHeaderPartial(name, Name, NAME, partial, useBootstrap, iconSet) {
59
+ const items = partial.items || ['dashboard', 'settings', 'profile', 'logout'];
60
+ let code = `<?php
61
+ /**
62
+ * Header partial: ${partial.name}
63
+ * Для шаблона админки admincoreui
64
+ */
65
+
66
+ $header_vars = [
67
+ 'addon_name' => '${name}',
68
+ 'items' => ${JSON.stringify(items)},
69
+ ];
70
+ `;
71
+ if (useBootstrap) {
72
+ code += `
73
+ <nav class="navbar navbar-expand-lg navbar-dark bg-primary">
74
+ <a class="navbar-brand" href="<?php echo href_to_home(); ?>">
75
+ <i class="${iconSet}home"></i>
76
+ <?php echo \\$cms_config->sitename; ?>
77
+ </a>
78
+
79
+ <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#${name}Navbar">
80
+ <span class="navbar-toggler-icon"></span>
81
+ </button>
82
+
83
+ <div class="collapse navbar-collapse" id="${name}Navbar">
84
+ <ul class="navbar-nav mr-auto">
85
+ `;
86
+ for (const item of items) {
87
+ const itemTitle = item.charAt(0).toUpperCase() + item.slice(1).replace(/_/g, ' ');
88
+ code += ` <li class="nav-item">
89
+ <a class="nav-link" href="<?php echo href_to('admin', '${item}'); ?>">
90
+ <i class="${iconSet}${item}"></i> ${itemTitle}
91
+ </a>
92
+ </li>
93
+ `;
94
+ }
95
+ code += ` </ul>
96
+
97
+ <ul class="navbar-nav">
98
+ <li class="nav-item dropdown">
99
+ <a class="nav-link dropdown-toggle" href="#" data-toggle="dropdown">
100
+ <i class="${iconSet}user"></i> <?php echo html(\\$this->cms_user->nickname); ?>
101
+ </a>
102
+ <div class="dropdown-menu dropdown-menu-right">
103
+ <a class="dropdown-item" href="<?php echo href_to('auth', 'profile'); ?>">
104
+ <i class="${iconSet}user-circle"></i> <?php echo LANG_PROFILE; ?>
105
+ </a>
106
+ <div class="dropdown-divider"></div>
107
+ <a class="dropdown-item" href="<?php echo href_to('auth', 'logout'); ?>">
108
+ <i class="${iconSet}sign-out"></i> <?php echo LANG_LOGOUT; ?>
109
+ </a>
110
+ </div>
111
+ </li>
112
+ </ul>
113
+ </div>
114
+ </nav>
115
+ `;
116
+ }
117
+ else {
118
+ code += `
119
+ <div class="${name}-header">
120
+ <div class="${name}-logo">
121
+ <a href="<?php echo href_to_home(); ?>"><?php echo \\$cms_config->sitename; ?></a>
122
+ </div>
123
+ <div class="${name}-menu">
124
+ `;
125
+ for (const item of items) {
126
+ const itemTitle = item.charAt(0).toUpperCase() + item.slice(1).replace(/_/g, ' ');
127
+ code += ` <a href="<?php echo href_to('admin', '${item}'); ?>" class="${name}-item">${itemTitle}</a>
128
+ `;
129
+ }
130
+ code += ` </div>
131
+ </div>
132
+ `;
133
+ }
134
+ return code;
135
+ }
136
+ function generateSidebarPartial(name, Name, NAME, partial, useBootstrap, iconSet) {
137
+ const items = partial.items || ['content', 'users', 'comments', 'photos'];
138
+ let code = `<?php
139
+ /**
140
+ * Sidebar partial: ${partial.name}
141
+ */
142
+
143
+ $sidebar_vars = [
144
+ 'addon_name' => '${name}',
145
+ 'items' => ${JSON.stringify(items)},
146
+ ];
147
+ `;
148
+ if (useBootstrap) {
149
+ code += `
150
+ <div class="${name}-sidebar bg-light">
151
+ <div class="list-group list-group-flush">
152
+ `;
153
+ for (const item of items) {
154
+ const itemTitle = item.charAt(0).toUpperCase() + item.slice(1).replace(/_/g, ' ');
155
+ code += ` <a href="<?php echo href_to('admin', '${item}'); ?>" class="list-group-item list-group-item-action">
156
+ <i class="${iconSet}${item}"></i> ${itemTitle}
157
+ </a>
158
+ `;
159
+ }
160
+ code += ` </div>
161
+ </div>
162
+ `;
163
+ }
164
+ else {
165
+ code += `
166
+ <div class="${name}-sidebar">
167
+ `;
168
+ for (const item of items) {
169
+ const itemTitle = item.charAt(0).toUpperCase() + item.slice(1).replace(/_/g, ' ');
170
+ code += ` <a href="<?php echo href_to('admin', '${item}'); ?>" class="${name}-item">${itemTitle}</a>
171
+ `;
172
+ }
173
+ code += `</div>
174
+ `;
175
+ }
176
+ return code;
177
+ }
178
+ function generateFooterPartial(name, Name, NAME, partial, useBootstrap, iconSet) {
179
+ let code = `<?php
180
+ /**
181
+ * Footer partial: ${partial.name}
182
+ */
183
+ `;
184
+ if (useBootstrap) {
185
+ code += `
186
+ <footer class="${name}-footer mt-5 py-3 bg-light">
187
+ <div class="container">
188
+ <div class="row">
189
+ <div class="col-md-6">
190
+ <p class="text-muted mb-0">
191
+ &copy; <?php echo date('Y'); ?> <?php echo \\$cms_config->sitename; ?>
192
+ </p>
193
+ </div>
194
+ <div class="col-md-6 text-md-right">
195
+ <p class="text-muted mb-0">
196
+ <a href="<?php echo href_to('admin'); ?>">
197
+ <i class="${iconSet}dashboard"></i> <?php echo LANG_ADMIN_PANEL; ?>
198
+ </a>
199
+ </p>
200
+ </div>
201
+ </div>
202
+ </div>
203
+ </footer>
204
+ `;
205
+ }
206
+ else {
207
+ code += `
208
+ <div class="${name}-footer">
209
+ <p>&copy; <?php echo date('Y'); ?> <?php echo \\$cms_config->sitename; ?></p>
210
+ </div>
211
+ `;
212
+ }
213
+ return code;
214
+ }
215
+ function generateToolbarPartial(name, Name, NAME, partial, useBootstrap, iconSet) {
216
+ const items = partial.items || ['add', 'edit', 'delete'];
217
+ let code = `<?php
218
+ /**
219
+ * Toolbar partial: ${partial.name}
220
+ */
221
+
222
+ $toolbar_vars = [
223
+ 'addon_name' => '${name}',
224
+ 'items' => ${JSON.stringify(items)},
225
+ ];
226
+ `;
227
+ if (useBootstrap) {
228
+ code += `
229
+ <div class="${name}-toolbar btn-toolbar mb-3" role="toolbar">
230
+ `;
231
+ for (const item of items) {
232
+ const itemTitle = item.charAt(0).toUpperCase() + item.slice(1).replace(/_/g, ' ');
233
+ code += ` <div class="btn-group mr-2">
234
+ <button type="button" class="btn btn-outline-secondary">
235
+ <i class="${iconSet}${item}"></i> ${itemTitle}
236
+ </button>
237
+ </div>
238
+ `;
239
+ }
240
+ code += `</div>
241
+ `;
242
+ }
243
+ else {
244
+ code += `
245
+ <div class="${name}-toolbar">
246
+ `;
247
+ for (const item of items) {
248
+ const itemTitle = item.charAt(0).toUpperCase() + item.slice(1).replace(/_/g, ' ');
249
+ code += ` <button class="${name}-btn ${name}-btn-${item}">${itemTitle}</button>
250
+ `;
251
+ }
252
+ code += `</div>
253
+ `;
254
+ }
255
+ return code;
256
+ }
257
+ function generateBreadcrumbPartial(name, Name, NAME, partial, useBootstrap, iconSet) {
258
+ let code = `<?php
259
+ /**
260
+ * Breadcrumb partial: ${partial.name}
261
+ */
262
+ `;
263
+ if (useBootstrap) {
264
+ code += `
265
+ <ol class="breadcrumb">
266
+ <li class="breadcrumb-item">
267
+ <a href="<?php echo href_to('admin'); ?>">
268
+ <i class="${iconSet}home"></i>
269
+ </a>
270
+ </li>
271
+ <?php if (!empty(\\$crumbs)) { ?>
272
+ <?php foreach (\\$crumbs as \\$crumb) { ?>
273
+ <li class="breadcrumb-item <?php echo \\$crumb['is_last'] ? 'active' : ''; ?>">
274
+ <?php if (!\\$crumb['is_last']) { ?>
275
+ <a href="<?php echo \\$crumb['href']; ?>"><?php echo \\$crumb['title']; ?></a>
276
+ <?php } else { ?>
277
+ <?php echo \\$crumb['title']; ?>
278
+ <?php } ?>
279
+ </li>
280
+ <?php } ?>
281
+ <?php } ?>
282
+ </ol>
283
+ `;
284
+ }
285
+ else {
286
+ code += `
287
+ <div class="${name}-breadcrumb">
288
+ <a href="<?php echo href_to('admin'); ?>">Главная</a>
289
+ <?php if (!empty(\\$crumbs)) { ?>
290
+ <?php foreach (\\$crumbs as \\$crumb) { ?>
291
+ &raquo; <a href="<?php echo \\$crumb['href']; ?>"><?php echo \\$crumb['title']; ?></a>
292
+ <?php } ?>
293
+ <?php } ?>
294
+ </div>
295
+ `;
296
+ }
297
+ return code;
298
+ }
299
+ function generatePanelPartial(name, Name, NAME, partial, useBootstrap, iconSet) {
300
+ let code = `<?php
301
+ /**
302
+ * Panel partial: ${partial.name}
303
+ */
304
+ `;
305
+ if (useBootstrap) {
306
+ code += `
307
+ <div class="card ${name}-panel">
308
+ <div class="card-header">
309
+ <h5 class="mb-0">
310
+ <i class="${iconSet}file"></i>
311
+ <?php echo \\$panel_title ?? 'Panel Title'; ?>
312
+ </h5>
313
+ </div>
314
+ <div class="card-body">
315
+ <?php echo \\$panel_content ?? ''; ?>
316
+ </div>
317
+ <?php if (!empty(\\$panel_footer)) { ?>
318
+ <div class="card-footer">
319
+ <?php echo \\$panel_footer; ?>
320
+ </div>
321
+ <?php } ?>
322
+ </div>
323
+ `;
324
+ }
325
+ else {
326
+ code += `
327
+ <div class="${name}-panel">
328
+ <div class="${name}-panel-header">
329
+ <h3><?php echo \\$panel_title ?? 'Panel Title'; ?></h3>
330
+ </div>
331
+ <div class="${name}-panel-body">
332
+ <?php echo \\$panel_content ?? ''; ?>
333
+ </div>
334
+ </div>
335
+ `;
336
+ }
337
+ return code;
338
+ }
339
+ function generateModalPartial(name, Name, NAME, partial, useBootstrap, iconSet) {
340
+ let code = `<?php
341
+ /**
342
+ * Modal partial: ${partial.name}
343
+ */
344
+ `;
345
+ if (useBootstrap) {
346
+ code += `
347
+ <!-- Modal: ${partial.name} -->
348
+ <div class="modal fade" id="${name}Modal" tabindex="-1" role="dialog">
349
+ <div class="modal-dialog" role="document">
350
+ <div class="modal-content">
351
+ <div class="modal-header">
352
+ <h5 class="modal-title">
353
+ <i class="${iconSet}modal"></i>
354
+ <?php echo \\$modal_title ?? 'Modal Title'; ?>
355
+ </h5>
356
+ <button type="button" class="close" data-dismiss="modal">
357
+ <span>&times;</span>
358
+ </button>
359
+ </div>
360
+ <div class="modal-body">
361
+ <?php echo \\$modal_content ?? ''; ?>
362
+ </div>
363
+ <?php if (!empty(\\$modal_footer)) { ?>
364
+ <div class="modal-footer">
365
+ <?php echo \\$modal_footer; ?>
366
+ </div>
367
+ <?php } ?>
368
+ </div>
369
+ </div>
370
+ </div>
371
+ `;
372
+ }
373
+ else {
374
+ code += `
375
+ <div class="${name}-modal" id="${name}Modal">
376
+ <div class="${name}-modal-dialog">
377
+ <div class="${name}-modal-content">
378
+ <div class="${name}-modal-header">
379
+ <h3><?php echo \\$modal_title ?? 'Modal Title'; ?></h3>
380
+ <button type="button" class="${name}-close" data-dismiss="modal">&times;</button>
381
+ </div>
382
+ <div class="${name}-modal-body">
383
+ <?php echo \\$modal_content ?? ''; ?>
384
+ </div>
385
+ </div>
386
+ </div>
387
+ </div>
388
+ `;
389
+ }
390
+ return code;
391
+ }
392
+ function generateNotificationPartial(name, Name, NAME, partial, useBootstrap, iconSet) {
393
+ let code = `<?php
394
+ /**
395
+ * Notification partial: ${partial.name}
396
+ */
397
+ `;
398
+ if (useBootstrap) {
399
+ code += `
400
+ <?php
401
+ \\$notices = cmsCore::getSessionFlash('notice');
402
+ if (\\$notices) {
403
+ foreach (\\$notices as \\$notice) { ?>
404
+ <div class="alert alert-<?php echo \\$notice['type'] ?? 'info'; ?> alert-dismissible fade show" role="alert">
405
+ <?php if (\\$notice['type'] === 'success') { ?>
406
+ <i class="${iconSet}check-circle"></i>
407
+ <?php } elseif (\\$notice['type'] === 'error') { ?>
408
+ <i class="${iconSet}exclamation-circle"></i>
409
+ <?php } else { ?>
410
+ <i class="${iconSet}info-circle"></i>
411
+ <?php } ?>
412
+ <?php echo \\$notice['text']; ?>
413
+ <button type="button" class="close" data-dismiss="alert">
414
+ <span>&times;</span>
415
+ </button>
416
+ </div>
417
+ <?php }
418
+ }
419
+ ?>
420
+ `;
421
+ }
422
+ else {
423
+ code += `
424
+ <?php
425
+ \\$notices = cmsCore::getSessionFlash('notice');
426
+ if (\\$notices) {
427
+ foreach (\\$notices as \\$notice) { ?>
428
+ <div class="${name}-notice ${name}-notice-<?php echo \\$notice['type'] ?? 'info'; ?>">
429
+ <?php echo \\$notice['text']; ?>
430
+ </div>
431
+ <?php }
432
+ }
433
+ ?>
434
+ `;
435
+ }
436
+ return code;
437
+ }
438
+ function generateGenericPartial(name, Name, NAME, partial, useBootstrap, iconSet) {
439
+ let code = `<?php
440
+ /**
441
+ * Partial: ${partial.name} (type: ${partial.type})
442
+ */
443
+
444
+ $vars = [
445
+ 'addon_name' => '${name}',
446
+ 'partial_name' => '${partial.name}',
447
+ 'partial_type' => '${partial.type}',
448
+ ];
449
+ `;
450
+ if (useBootstrap) {
451
+ code += `
452
+ <div class="${name}-partial ${name}-${partial.type}">
453
+ <div class="card">
454
+ <div class="card-body">
455
+ <h5 class="card-title">
456
+ <i class="${iconSet}file"></i>
457
+ <?php echo \\$partial_title ?? '${capitalize(partial.name.replace(/_/g, ' '))}'; ?>
458
+ </h5>
459
+ <div class="card-text">
460
+ <?php echo \\$partial_content ?? ''; ?>
461
+ </div>
462
+ </div>
463
+ </div>
464
+ </div>
465
+ `;
466
+ }
467
+ else {
468
+ code += `
469
+ <div class="${name}-partial ${name}-${partial.type}">
470
+ <h4><?php echo \\$partial_title ?? '${capitalize(partial.name.replace(/_/g, ' '))}'; ?></h4>
471
+ <div class="${name}-content">
472
+ <?php echo \\$partial_content ?? ''; ?>
473
+ </div>
474
+ </div>
475
+ `;
476
+ }
477
+ return code;
478
+ }
479
+ function generateIndexPartial(name, Name, NAME, partials) {
480
+ let code = `<?php
481
+ /**
482
+ * Index файл для части админки: ${name}
483
+ * Подключает все partials этого набора
484
+ */
485
+
486
+ `;
487
+ for (const partial of partials) {
488
+ code += `// Подключение: $this->renderPartial('${name}', '${name}_${partial.type}_${partial.name}', $vars);
489
+ `;
490
+ }
491
+ code += `
492
+
493
+ // Использование в контроллере:
494
+ // $this->renderPartial('${name}', 'header', ['items' => $items]);
495
+ // $this->renderPartial('${name}', 'sidebar', ['items' => $menu_items]);
496
+ `;
497
+ return code;
498
+ }