@maz-ui/mcp 5.0.1-beta.0 → 5.1.0-beta.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.
- package/README.md +61 -228
- package/bin/maz-ui-mcp.mjs +2 -5
- package/dist/cli.d.mts +7 -0
- package/dist/cli.d.ts +7 -0
- package/dist/cli.mjs +14 -0
- package/dist/index.d.mts +340 -0
- package/dist/index.d.ts +340 -0
- package/dist/index.mjs +14 -0
- package/dist/shared/mcp.DzqVbCaL.mjs +2346 -0
- package/docs/README.md +207 -0
- package/docs/agents/agents-md.md +52 -0
- package/docs/agents/claude-rule.md +52 -0
- package/docs/components/maz-accordion.md +76 -0
- package/docs/{src/components → components}/maz-alert.md +31 -164
- package/docs/components/maz-animated-counter.md +87 -0
- package/docs/components/maz-animated-element.md +46 -0
- package/docs/components/maz-animated-text.md +53 -0
- package/docs/components/maz-avatar.md +193 -0
- package/docs/components/maz-backdrop.md +178 -0
- package/docs/{src/components → components}/maz-badge.md +26 -67
- package/docs/components/maz-bottom-sheet.md +257 -0
- package/docs/{src/components → components}/maz-btn-group.md +26 -189
- package/docs/{src/components → components}/maz-btn.md +60 -245
- package/docs/components/maz-card-spotlight.md +84 -0
- package/docs/{src/components → components}/maz-card.md +67 -192
- package/docs/components/maz-carousel.md +153 -0
- package/docs/{src/components → components}/maz-chart.md +17 -161
- package/docs/components/maz-checkbox.md +138 -0
- package/docs/components/maz-checklist.md +251 -0
- package/docs/components/maz-circular-progress-bar.md +109 -0
- package/docs/{src/components → components}/maz-code-highlight.md +15 -93
- package/docs/components/maz-container.md +241 -0
- package/docs/{src/components → components}/maz-date-picker.md +85 -454
- package/docs/components/maz-dialog-confirm.md +215 -0
- package/docs/components/maz-dialog.md +143 -0
- package/docs/components/maz-drawer.md +106 -0
- package/docs/components/maz-dropdown.md +419 -0
- package/docs/{src/components → components}/maz-dropzone.md +80 -221
- package/docs/components/maz-expand-animation.md +82 -0
- package/docs/components/maz-fullscreen-loader.md +58 -0
- package/docs/components/maz-gallery.md +79 -0
- package/docs/{src/components → components}/maz-icon.md +32 -83
- package/docs/components/maz-input-code.md +73 -0
- package/docs/components/maz-input-number.md +79 -0
- package/docs/components/maz-input-phone-number.md +536 -0
- package/docs/components/maz-input-price.md +68 -0
- package/docs/components/maz-input-tags.md +112 -0
- package/docs/{src/components → components}/maz-input.md +74 -221
- package/docs/components/maz-lazy-img.md +113 -0
- package/docs/components/maz-link.md +146 -0
- package/docs/components/maz-loading-bar.md +38 -0
- package/docs/{src/components → components}/maz-markdown-editor.md +72 -125
- package/docs/components/maz-pagination.md +82 -0
- package/docs/components/maz-popover.md +794 -0
- package/docs/{src/components → components}/maz-pull-to-refresh.md +59 -45
- package/docs/components/maz-radio-buttons.md +313 -0
- package/docs/components/maz-radio.md +119 -0
- package/docs/{src/components → components}/maz-read-more.md +31 -122
- package/docs/components/maz-reading-progress-bar.md +96 -0
- package/docs/{src/components → components}/maz-select-country.md +80 -340
- package/docs/{src/components → components}/maz-select.md +76 -206
- package/docs/components/maz-sidebar-content.md +25 -0
- package/docs/components/maz-sidebar-footer.md +25 -0
- package/docs/components/maz-sidebar-group.md +27 -0
- package/docs/components/maz-sidebar-header.md +25 -0
- package/docs/components/maz-sidebar-menu-button.md +41 -0
- package/docs/components/maz-sidebar-menu-item.md +25 -0
- package/docs/components/maz-sidebar-menu-sub.md +32 -0
- package/docs/components/maz-sidebar-menu.md +25 -0
- package/docs/components/maz-sidebar-separator.md +21 -0
- package/docs/components/maz-sidebar-trigger.md +25 -0
- package/docs/{src/components → components}/maz-sidebar.md +117 -329
- package/docs/{src/components → components}/maz-skeleton.md +27 -156
- package/docs/{src/components → components}/maz-slider.md +33 -66
- package/docs/components/maz-spinner.md +84 -0
- package/docs/{src/components → components}/maz-stepper.md +43 -185
- package/docs/components/maz-switch.md +86 -0
- package/docs/components/maz-table-cell.md +27 -0
- package/docs/components/maz-table-row.md +28 -0
- package/docs/components/maz-table-title.md +27 -0
- package/docs/components/maz-table-virtualizer.md +31 -0
- package/docs/components/maz-table.md +426 -0
- package/docs/components/maz-tabs-bar.md +43 -0
- package/docs/components/maz-tabs-content-item.md +27 -0
- package/docs/components/maz-tabs-content.md +27 -0
- package/docs/{src/components → components}/maz-tabs.md +89 -126
- package/docs/components/maz-textarea.md +255 -0
- package/docs/components/maz-ticker.md +427 -0
- package/docs/components/maz-timeline.md +304 -0
- package/docs/components/maz-ui-provider.md +26 -0
- package/docs/{src/components → components}/maz-window-mockup.md +38 -105
- package/docs/composables/use-aos.md +41 -0
- package/docs/composables/use-breakpoints.md +42 -0
- package/docs/composables/use-dialog.md +58 -0
- package/docs/{src/composables → composables}/use-display-names.md +12 -59
- package/docs/{src/composables → composables}/use-drag.md +14 -68
- package/docs/{src/composables → composables}/use-form-validator.md +22 -696
- package/docs/{src/composables → composables}/use-idle-timeout.md +13 -97
- package/docs/{src/composables → composables}/use-pull-to-refresh.md +14 -7
- package/docs/{src/composables → composables}/use-reading-time.md +20 -56
- package/docs/composables/use-string-matching.md +41 -0
- package/docs/{src/composables → composables}/use-swipe.md +14 -81
- package/docs/{src/composables → composables}/use-timer.md +12 -38
- package/docs/composables/use-toast.md +50 -0
- package/docs/{src/composables → composables}/use-user-visibility.md +14 -56
- package/docs/composables/use-wait.md +50 -0
- package/docs/composables/use-window-size.md +25 -0
- package/docs/{src/directives → directives}/click-outside.md +13 -99
- package/docs/{src/directives → directives}/fullscreen-img.md +10 -28
- package/docs/{src/directives → directives}/lazy-img.md +14 -49
- package/docs/{src/directives → directives}/tooltip.md +12 -217
- package/docs/{src/directives → directives}/zoom-img.md +11 -38
- package/docs/{src/ecosystem → ecosystem}/eslint-config.md +37 -29
- package/docs/ecosystem/icons/icon-set.md +25 -0
- package/docs/{src/ecosystem → ecosystem}/icons/index.md +22 -16
- package/docs/ecosystem/mcp.md +165 -0
- package/docs/{src/ecosystem → ecosystem}/node/exec-promise.md +12 -6
- package/docs/ecosystem/node/index.md +53 -0
- package/docs/{src/ecosystem → ecosystem}/node/logger.md +12 -6
- package/docs/{src/ecosystem → ecosystem}/node/print-banner.md +12 -4
- package/docs/ecosystem/node/setup-agents.md +102 -0
- package/docs/{src/ecosystem → ecosystem}/nuxt.md +46 -19
- package/docs/{src/ecosystem → ecosystem}/stylelint-config.md +33 -25
- package/docs/{src/ecosystem → ecosystem}/themes.md +72 -235
- package/docs/{src/ecosystem → ecosystem}/translations.md +25 -23
- package/docs/ecosystem/utils/camel-case.md +37 -0
- package/docs/ecosystem/utils/capitalize.md +37 -0
- package/docs/{src/ecosystem → ecosystem}/utils/check-availability.md +14 -8
- package/docs/{src/ecosystem → ecosystem}/utils/cookie.md +18 -12
- package/docs/ecosystem/utils/country-code-to-unicode-flag.md +128 -0
- package/docs/{src/ecosystem → ecosystem}/utils/currency.md +12 -26
- package/docs/{src/ecosystem → ecosystem}/utils/date.md +10 -24
- package/docs/ecosystem/utils/debounce-callback.md +44 -0
- package/docs/{src/ecosystem → ecosystem}/utils/debounce-id.md +14 -8
- package/docs/{src/ecosystem → ecosystem}/utils/debounce.md +14 -8
- package/docs/ecosystem/utils/fetch-locale-ip.md +39 -0
- package/docs/{src/ecosystem → ecosystem}/utils/format-json.md +11 -5
- package/docs/{src/ecosystem → ecosystem}/utils/format-phone-number.md +12 -6
- package/docs/ecosystem/utils/get-browser-locale.md +35 -0
- package/docs/ecosystem/utils/get-country-flag-url.md +67 -0
- package/docs/{src/ecosystem → ecosystem}/utils/get-error-message.md +10 -4
- package/docs/{src/ecosystem → ecosystem}/utils/idle-timeout.md +15 -9
- package/docs/{src/ecosystem → ecosystem}/utils/index.md +10 -13
- package/docs/{src/ecosystem → ecosystem}/utils/is-client.md +11 -5
- package/docs/{src/ecosystem → ecosystem}/utils/is-equal.md +14 -8
- package/docs/{src/ecosystem → ecosystem}/utils/is-ios.md +12 -6
- package/docs/ecosystem/utils/is-server.md +37 -0
- package/docs/ecosystem/utils/is-standalone-mode.md +49 -0
- package/docs/{src/ecosystem → ecosystem}/utils/kebab-case.md +10 -4
- package/docs/{src/ecosystem → ecosystem}/utils/normalize-string.md +10 -4
- package/docs/{src/ecosystem → ecosystem}/utils/number.md +10 -24
- package/docs/{src/ecosystem → ecosystem}/utils/pascal-case.md +11 -5
- package/docs/{src/ecosystem → ecosystem}/utils/prevent-ios-input-zoom.md +14 -8
- package/docs/{src/ecosystem → ecosystem}/utils/script-loader.md +16 -8
- package/docs/{src/ecosystem → ecosystem}/utils/sleep.md +10 -4
- package/docs/{src/ecosystem → ecosystem}/utils/snake-case.md +10 -4
- package/docs/{src/ecosystem → ecosystem}/utils/swipe-handler.md +14 -8
- package/docs/{src/ecosystem → ecosystem}/utils/textarea-autogrow.md +12 -6
- package/docs/{src/ecosystem → ecosystem}/utils/throttle-id.md +13 -7
- package/docs/{src/ecosystem → ecosystem}/utils/throttle.md +14 -8
- package/docs/ecosystem/utils/truthy-filter.md +37 -0
- package/docs/{src/ecosystem → ecosystem}/utils/types/deep-key-of.md +11 -5
- package/docs/{src/ecosystem → ecosystem}/utils/types/deep-partial.md +10 -4
- package/docs/ecosystem/utils/types/deep-required.md +45 -0
- package/docs/ecosystem/utils/types/flatten-object-keys.md +50 -0
- package/docs/{src/ecosystem → ecosystem}/utils/types/generic-instance-type.md +10 -4
- package/docs/{src/ecosystem → ecosystem}/utils/types/infer-maybe-ref.md +10 -4
- package/docs/ecosystem/utils/upper-first.md +38 -0
- package/docs/{src/ecosystem → ecosystem}/utils/user-visibility.md +12 -6
- package/docs/guide/ai-agents.md +237 -0
- package/docs/{src/guide → guide}/browser-support.md +22 -15
- package/docs/{src/guide → guide}/getting-started.md +34 -139
- package/docs/{src/guide → guide}/global-defaults.md +12 -11
- package/docs/{src/guide → guide}/maz-ui-provider.md +17 -16
- package/docs/{src/guide → guide}/migration-v5.md +95 -88
- package/docs/{src/guide → guide}/resolvers.md +33 -100
- package/docs/guide/tailwind.md +483 -0
- package/docs/{src/guide → guide}/vue.md +33 -39
- package/docs/manifest.json +1 -0
- package/docs/{src/plugins → plugins}/aos.md +20 -55
- package/docs/{src/plugins → plugins}/dialog.md +14 -161
- package/docs/plugins/toast.md +221 -0
- package/docs/plugins/wait.md +78 -0
- package/docs/reference/icons.md +46 -0
- package/docs/reference/tailwind-tokens.md +191 -0
- package/docs/rules.md +57 -0
- package/package.json +84 -22
- package/dist/mcp.d.mts +0 -153
- package/dist/mcp.d.ts +0 -153
- package/dist/mcp.mjs +0 -1511
- package/docs/generated-docs/maz-accordion.doc.md +0 -21
- package/docs/generated-docs/maz-alert.doc.md +0 -20
- package/docs/generated-docs/maz-animated-counter.doc.md +0 -17
- package/docs/generated-docs/maz-animated-element.doc.md +0 -14
- package/docs/generated-docs/maz-animated-text.doc.md +0 -17
- package/docs/generated-docs/maz-avatar.doc.md +0 -45
- package/docs/generated-docs/maz-backdrop.doc.md +0 -55
- package/docs/generated-docs/maz-badge.doc.md +0 -16
- package/docs/generated-docs/maz-bottom-sheet.doc.md +0 -24
- package/docs/generated-docs/maz-btn-group.doc.md +0 -20
- package/docs/generated-docs/maz-btn.doc.md +0 -33
- package/docs/generated-docs/maz-card-spotlight.doc.md +0 -16
- package/docs/generated-docs/maz-card.doc.md +0 -39
- package/docs/generated-docs/maz-carousel.doc.md +0 -17
- package/docs/generated-docs/maz-chart.doc.md +0 -10
- package/docs/generated-docs/maz-checkbox.doc.md +0 -33
- package/docs/generated-docs/maz-checklist.doc.md +0 -30
- package/docs/generated-docs/maz-circular-progress-bar.doc.md +0 -27
- package/docs/generated-docs/maz-code-highlight.doc.md +0 -11
- package/docs/generated-docs/maz-container.doc.md +0 -26
- package/docs/generated-docs/maz-date-picker.doc.md +0 -56
- package/docs/generated-docs/maz-dialog-confirm.doc.md +0 -24
- package/docs/generated-docs/maz-dialog.doc.md +0 -22
- package/docs/generated-docs/maz-drawer.doc.md +0 -25
- package/docs/generated-docs/maz-dropdown.doc.md +0 -45
- package/docs/generated-docs/maz-dropzone.doc.md +0 -82
- package/docs/generated-docs/maz-expand-animation.doc.md +0 -12
- package/docs/generated-docs/maz-fullscreen-loader.doc.md +0 -13
- package/docs/generated-docs/maz-gallery.doc.md +0 -17
- package/docs/generated-docs/maz-icon.doc.md +0 -16
- package/docs/generated-docs/maz-input-code.doc.md +0 -25
- package/docs/generated-docs/maz-input-number.doc.md +0 -33
- package/docs/generated-docs/maz-input-phone-number.doc.md +0 -62
- package/docs/generated-docs/maz-input-price.doc.md +0 -26
- package/docs/generated-docs/maz-input-tags.doc.md +0 -24
- package/docs/generated-docs/maz-input.doc.md +0 -54
- package/docs/generated-docs/maz-lazy-img.doc.md +0 -49
- package/docs/generated-docs/maz-link.doc.md +0 -31
- package/docs/generated-docs/maz-loading-bar.doc.md +0 -6
- package/docs/generated-docs/maz-markdown-editor.doc.md +0 -65
- package/docs/generated-docs/maz-pagination.doc.md +0 -21
- package/docs/generated-docs/maz-popover.doc.md +0 -79
- package/docs/generated-docs/maz-pull-to-refresh.doc.md +0 -50
- package/docs/generated-docs/maz-radio-buttons.doc.md +0 -34
- package/docs/generated-docs/maz-radio.doc.md +0 -33
- package/docs/generated-docs/maz-read-more.doc.md +0 -18
- package/docs/generated-docs/maz-reading-progress-bar.doc.md +0 -18
- package/docs/generated-docs/maz-select-country.doc.md +0 -45
- package/docs/generated-docs/maz-select.doc.md +0 -32
- package/docs/generated-docs/maz-sidebar-content.doc.md +0 -5
- package/docs/generated-docs/maz-sidebar-footer.doc.md +0 -5
- package/docs/generated-docs/maz-sidebar-group.doc.md +0 -11
- package/docs/generated-docs/maz-sidebar-header.doc.md +0 -5
- package/docs/generated-docs/maz-sidebar-menu-button.doc.md +0 -27
- package/docs/generated-docs/maz-sidebar-menu-item.doc.md +0 -5
- package/docs/generated-docs/maz-sidebar-menu-sub.doc.md +0 -16
- package/docs/generated-docs/maz-sidebar-menu.doc.md +0 -5
- package/docs/generated-docs/maz-sidebar-separator.doc.md +0 -0
- package/docs/generated-docs/maz-sidebar-trigger.doc.md +0 -5
- package/docs/generated-docs/maz-sidebar.doc.md +0 -36
- package/docs/generated-docs/maz-skeleton.doc.md +0 -12
- package/docs/generated-docs/maz-slider.doc.md +0 -20
- package/docs/generated-docs/maz-spinner.doc.md +0 -6
- package/docs/generated-docs/maz-stepper.doc.md +0 -30
- package/docs/generated-docs/maz-switch.doc.md +0 -31
- package/docs/generated-docs/maz-table-cell.doc.md +0 -5
- package/docs/generated-docs/maz-table-row.doc.md +0 -12
- package/docs/generated-docs/maz-table-title.doc.md +0 -5
- package/docs/generated-docs/maz-table-virtualizer.doc.md +0 -20
- package/docs/generated-docs/maz-table.doc.md +0 -72
- package/docs/generated-docs/maz-tabs-bar.doc.md +0 -29
- package/docs/generated-docs/maz-tabs-content-item.doc.md +0 -11
- package/docs/generated-docs/maz-tabs-content.doc.md +0 -5
- package/docs/generated-docs/maz-tabs.doc.md +0 -20
- package/docs/generated-docs/maz-textarea.doc.md +0 -46
- package/docs/generated-docs/maz-ticker.doc.md +0 -25
- package/docs/generated-docs/maz-timeline.doc.md +0 -32
- package/docs/generated-docs/maz-ui-provider.doc.md +0 -12
- package/docs/generated-docs/maz-window-mockup.doc.md +0 -23
- package/docs/src/blog/v4.md +0 -276
- package/docs/src/blog/v5.md +0 -184
- package/docs/src/changelog.md +0 -7
- package/docs/src/components/index.md +0 -8
- package/docs/src/components/maz-accordion.md +0 -80
- package/docs/src/components/maz-animated-counter.md +0 -124
- package/docs/src/components/maz-animated-element.md +0 -36
- package/docs/src/components/maz-animated-text.md +0 -36
- package/docs/src/components/maz-avatar.md +0 -227
- package/docs/src/components/maz-backdrop.md +0 -250
- package/docs/src/components/maz-bottom-sheet.md +0 -533
- package/docs/src/components/maz-card-spotlight.md +0 -163
- package/docs/src/components/maz-carousel.md +0 -231
- package/docs/src/components/maz-checkbox.md +0 -168
- package/docs/src/components/maz-checklist.md +0 -414
- package/docs/src/components/maz-circular-progress-bar.md +0 -145
- package/docs/src/components/maz-container.md +0 -363
- package/docs/src/components/maz-dialog-confirm.md +0 -240
- package/docs/src/components/maz-dialog.md +0 -164
- package/docs/src/components/maz-drawer.md +0 -181
- package/docs/src/components/maz-dropdown.md +0 -691
- package/docs/src/components/maz-expand-animation.md +0 -99
- package/docs/src/components/maz-fullscreen-loader.md +0 -58
- package/docs/src/components/maz-gallery.md +0 -85
- package/docs/src/components/maz-input-code.md +0 -61
- package/docs/src/components/maz-input-number.md +0 -81
- package/docs/src/components/maz-input-phone-number.md +0 -942
- package/docs/src/components/maz-input-price.md +0 -67
- package/docs/src/components/maz-input-tags.md +0 -114
- package/docs/src/components/maz-lazy-img.md +0 -88
- package/docs/src/components/maz-link.md +0 -178
- package/docs/src/components/maz-loading-bar.md +0 -26
- package/docs/src/components/maz-pagination.md +0 -79
- package/docs/src/components/maz-popover.md +0 -1416
- package/docs/src/components/maz-radio-buttons.md +0 -462
- package/docs/src/components/maz-radio.md +0 -142
- package/docs/src/components/maz-reading-progress-bar.md +0 -74
- package/docs/src/components/maz-spinner.md +0 -93
- package/docs/src/components/maz-switch.md +0 -92
- package/docs/src/components/maz-table.md +0 -732
- package/docs/src/components/maz-textarea.md +0 -400
- package/docs/src/components/maz-ticker.md +0 -692
- package/docs/src/components/maz-timeline.md +0 -478
- package/docs/src/composables/use-aos.md +0 -34
- package/docs/src/composables/use-breakpoints.md +0 -35
- package/docs/src/composables/use-dialog.md +0 -88
- package/docs/src/composables/use-string-matching.md +0 -63
- package/docs/src/composables/use-toast.md +0 -71
- package/docs/src/composables/use-wait.md +0 -62
- package/docs/src/composables/use-window-size.md +0 -18
- package/docs/src/ecosystem/icons/icon-set.md +0 -123
- package/docs/src/ecosystem/mcp.md +0 -210
- package/docs/src/ecosystem/node/index.md +0 -53
- package/docs/src/ecosystem/utils/camel-case.md +0 -31
- package/docs/src/ecosystem/utils/capitalize.md +0 -50
- package/docs/src/ecosystem/utils/country-code-to-unicode-flag.md +0 -213
- package/docs/src/ecosystem/utils/debounce-callback.md +0 -38
- package/docs/src/ecosystem/utils/fetch-locale-ip.md +0 -33
- package/docs/src/ecosystem/utils/get-browser-locale.md +0 -29
- package/docs/src/ecosystem/utils/get-country-flag-url.md +0 -156
- package/docs/src/ecosystem/utils/is-server.md +0 -31
- package/docs/src/ecosystem/utils/is-standalone-mode.md +0 -43
- package/docs/src/ecosystem/utils/truthy-filter.md +0 -31
- package/docs/src/ecosystem/utils/types/deep-required.md +0 -39
- package/docs/src/ecosystem/utils/types/flatten-object-keys.md +0 -44
- package/docs/src/ecosystem/utils/upper-first.md +0 -32
- package/docs/src/guide/cli.md +0 -144
- package/docs/src/guide/migration-v4.md +0 -925
- package/docs/src/guide/tailwind.md +0 -158
- package/docs/src/index.md +0 -603
- package/docs/src/made-with-maz-ui.md +0 -58
- package/docs/src/plugins/toast.md +0 -349
- package/docs/src/plugins/wait.md +0 -109
- package/docs/src/theme-editor.md +0 -21
package/dist/mcp.mjs
DELETED
|
@@ -1,1511 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { getErrorMessage } from '@maz-ui/utils/helpers/getErrorMessage';
|
|
3
|
-
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
4
|
-
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
5
|
-
import { ListResourcesRequestSchema, ReadResourceRequestSchema, ListToolsRequestSchema, CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
6
|
-
import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
|
|
7
|
-
import { resolve, join, dirname } from 'node:path';
|
|
8
|
-
import { fileURLToPath } from 'node:url';
|
|
9
|
-
|
|
10
|
-
const version = "5.0.0";
|
|
11
|
-
|
|
12
|
-
class MetadataExtractor {
|
|
13
|
-
extract(name, type, content, manualTags = []) {
|
|
14
|
-
const frontmatter = this.extractFrontmatter(content);
|
|
15
|
-
const sections = this.extractSections(content);
|
|
16
|
-
const props = this.extractProps(content);
|
|
17
|
-
const slots = this.extractSlots(content);
|
|
18
|
-
const events = this.extractEvents(content);
|
|
19
|
-
const displayName = frontmatter.title ?? this.nameToDisplayName(name);
|
|
20
|
-
const description = frontmatter.description ?? this.extractFirstParagraph(content);
|
|
21
|
-
const extractedTags = this.buildTags(name, displayName, props, slots, events);
|
|
22
|
-
const tags = this.mergeTags(manualTags, extractedTags);
|
|
23
|
-
return {
|
|
24
|
-
name,
|
|
25
|
-
displayName,
|
|
26
|
-
type,
|
|
27
|
-
description,
|
|
28
|
-
tags,
|
|
29
|
-
...props.length > 0 && { props },
|
|
30
|
-
...slots.length > 0 && { slots },
|
|
31
|
-
...events.length > 0 && { events },
|
|
32
|
-
sections
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
extractFrontmatter(content) {
|
|
36
|
-
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
37
|
-
if (!match) {
|
|
38
|
-
return {};
|
|
39
|
-
}
|
|
40
|
-
const result = {};
|
|
41
|
-
const yaml = match[1];
|
|
42
|
-
for (const line of yaml.split("\n")) {
|
|
43
|
-
const trimmed = line.trim();
|
|
44
|
-
if (trimmed.startsWith("title:")) {
|
|
45
|
-
result.title = trimmed.slice("title:".length).trim();
|
|
46
|
-
} else if (trimmed.startsWith("description:")) {
|
|
47
|
-
result.description = trimmed.slice("description:".length).trim();
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
return result;
|
|
51
|
-
}
|
|
52
|
-
extractSections(content) {
|
|
53
|
-
const sections = [];
|
|
54
|
-
const contentWithoutFrontmatter = this.stripFrontmatter(content);
|
|
55
|
-
const lines = contentWithoutFrontmatter.split("\n");
|
|
56
|
-
let currentSection;
|
|
57
|
-
const flushSection = () => {
|
|
58
|
-
if (currentSection) {
|
|
59
|
-
const sectionContent = currentSection.contentLines.join("\n").trim();
|
|
60
|
-
sections.push({
|
|
61
|
-
title: currentSection.title,
|
|
62
|
-
level: currentSection.level,
|
|
63
|
-
content: this.extractSectionLeadText(sectionContent)
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
for (const line of lines) {
|
|
68
|
-
const headingMatch = line.match(/^(#{2,3}) +(\S.*)$/);
|
|
69
|
-
if (headingMatch) {
|
|
70
|
-
flushSection();
|
|
71
|
-
currentSection = {
|
|
72
|
-
level: headingMatch[1].length,
|
|
73
|
-
title: this.cleanHeadingText(headingMatch[2]),
|
|
74
|
-
contentLines: []
|
|
75
|
-
};
|
|
76
|
-
} else if (currentSection) {
|
|
77
|
-
currentSection.contentLines.push(line);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
flushSection();
|
|
81
|
-
return sections;
|
|
82
|
-
}
|
|
83
|
-
extractProps(content) {
|
|
84
|
-
return this.extractTableColumn(content, "Props", "Name");
|
|
85
|
-
}
|
|
86
|
-
extractSlots(content) {
|
|
87
|
-
return this.extractTableColumn(content, "Slots", "Name");
|
|
88
|
-
}
|
|
89
|
-
extractEvents(content) {
|
|
90
|
-
return this.extractTableColumn(content, "Events", "Event name");
|
|
91
|
-
}
|
|
92
|
-
mergeTags(manualTags, extractedTags) {
|
|
93
|
-
const tagSet = /* @__PURE__ */ new Set();
|
|
94
|
-
for (const tag of manualTags) {
|
|
95
|
-
tagSet.add(tag.toLowerCase());
|
|
96
|
-
}
|
|
97
|
-
for (const tag of extractedTags) {
|
|
98
|
-
tagSet.add(tag.toLowerCase());
|
|
99
|
-
}
|
|
100
|
-
return Array.from(tagSet);
|
|
101
|
-
}
|
|
102
|
-
extractTableColumn(content, sectionName, columnName) {
|
|
103
|
-
const sectionRegex = new RegExp(`## ${sectionName} *\\n`, "i");
|
|
104
|
-
const sectionMatch = content.match(sectionRegex);
|
|
105
|
-
if (!sectionMatch || sectionMatch.index === void 0) {
|
|
106
|
-
return [];
|
|
107
|
-
}
|
|
108
|
-
const afterSection = content.slice(sectionMatch.index + sectionMatch[0].length);
|
|
109
|
-
const lines = afterSection.split("\n");
|
|
110
|
-
const headerLine = lines.find((l) => l.includes("|") && l.toLowerCase().includes(columnName.toLowerCase()));
|
|
111
|
-
if (!headerLine) {
|
|
112
|
-
return [];
|
|
113
|
-
}
|
|
114
|
-
const headerIndex = lines.indexOf(headerLine);
|
|
115
|
-
const columns = headerLine.split("|").map((c) => c.trim()).filter(Boolean);
|
|
116
|
-
const nameColumnIndex = columns.findIndex((c) => c.toLowerCase().includes(columnName.toLowerCase()));
|
|
117
|
-
if (nameColumnIndex === -1) {
|
|
118
|
-
return [];
|
|
119
|
-
}
|
|
120
|
-
const results = [];
|
|
121
|
-
for (let i = headerIndex + 2; i < lines.length; i++) {
|
|
122
|
-
const line = lines[i];
|
|
123
|
-
if (!line.includes("|") || line.match(/^#{1,6}\s/)) {
|
|
124
|
-
break;
|
|
125
|
-
}
|
|
126
|
-
if (line.match(/^ *\|[-\s|]+\| *$/)) {
|
|
127
|
-
continue;
|
|
128
|
-
}
|
|
129
|
-
const cells = line.split("|").map((c) => c.trim()).filter(Boolean);
|
|
130
|
-
if (cells[nameColumnIndex]) {
|
|
131
|
-
const name = cells[nameColumnIndex].replace(/\*\*/g, "").trim();
|
|
132
|
-
if (name) {
|
|
133
|
-
results.push(name);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
return results;
|
|
138
|
-
}
|
|
139
|
-
stripFrontmatter(content) {
|
|
140
|
-
return content.replace(/^---\n[\s\S]*?\n---\n?/, "");
|
|
141
|
-
}
|
|
142
|
-
cleanHeadingText(text) {
|
|
143
|
-
let result = this.removeTemplateTags(text);
|
|
144
|
-
result = this.resolveMarkdownLinks(result);
|
|
145
|
-
return result.trim();
|
|
146
|
-
}
|
|
147
|
-
removeTemplateTags(text) {
|
|
148
|
-
let result = "";
|
|
149
|
-
let i = 0;
|
|
150
|
-
while (i < text.length) {
|
|
151
|
-
if (text[i] === "{" && text[i + 1] === "{") {
|
|
152
|
-
const end = text.indexOf("}}", i + 2);
|
|
153
|
-
i = end === -1 ? text.length : end + 2;
|
|
154
|
-
} else {
|
|
155
|
-
result += text[i];
|
|
156
|
-
i++;
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
return result;
|
|
160
|
-
}
|
|
161
|
-
resolveMarkdownLinks(text) {
|
|
162
|
-
let result = "";
|
|
163
|
-
let i = 0;
|
|
164
|
-
while (i < text.length) {
|
|
165
|
-
if (text[i] === "[") {
|
|
166
|
-
const closeBracket = text.indexOf("]", i + 1);
|
|
167
|
-
if (closeBracket !== -1 && text[closeBracket + 1] === "(") {
|
|
168
|
-
const closeParen = text.indexOf(")", closeBracket + 2);
|
|
169
|
-
if (closeParen !== -1) {
|
|
170
|
-
result += text.slice(i + 1, closeBracket);
|
|
171
|
-
i = closeParen + 1;
|
|
172
|
-
continue;
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
result += text[i];
|
|
177
|
-
i++;
|
|
178
|
-
}
|
|
179
|
-
return result;
|
|
180
|
-
}
|
|
181
|
-
extractSectionLeadText(content) {
|
|
182
|
-
const lines = content.split("\n");
|
|
183
|
-
const paragraphLines = [];
|
|
184
|
-
for (const line of lines) {
|
|
185
|
-
const trimmed = line.trim();
|
|
186
|
-
if (!trimmed) {
|
|
187
|
-
if (paragraphLines.length > 0) {
|
|
188
|
-
break;
|
|
189
|
-
}
|
|
190
|
-
continue;
|
|
191
|
-
}
|
|
192
|
-
if (trimmed.startsWith("#") || trimmed.startsWith("<") || trimmed.startsWith("```") || trimmed.startsWith(":::") || trimmed.startsWith("|")) {
|
|
193
|
-
if (paragraphLines.length > 0) {
|
|
194
|
-
break;
|
|
195
|
-
}
|
|
196
|
-
continue;
|
|
197
|
-
}
|
|
198
|
-
paragraphLines.push(trimmed);
|
|
199
|
-
}
|
|
200
|
-
return paragraphLines.join(" ");
|
|
201
|
-
}
|
|
202
|
-
extractFirstParagraph(content) {
|
|
203
|
-
const stripped = this.stripFrontmatter(content);
|
|
204
|
-
const lines = stripped.split("\n");
|
|
205
|
-
const paragraphLines = [];
|
|
206
|
-
for (const line of lines) {
|
|
207
|
-
const trimmed = line.trim();
|
|
208
|
-
if (!trimmed) {
|
|
209
|
-
if (paragraphLines.length > 0) {
|
|
210
|
-
break;
|
|
211
|
-
}
|
|
212
|
-
continue;
|
|
213
|
-
}
|
|
214
|
-
if (trimmed.startsWith("#") || trimmed.startsWith("<") || trimmed.startsWith("```") || trimmed.startsWith(":::") || trimmed.startsWith("|") || trimmed.startsWith("{{")) {
|
|
215
|
-
if (paragraphLines.length > 0) {
|
|
216
|
-
break;
|
|
217
|
-
}
|
|
218
|
-
continue;
|
|
219
|
-
}
|
|
220
|
-
paragraphLines.push(trimmed);
|
|
221
|
-
}
|
|
222
|
-
return paragraphLines.join(" ");
|
|
223
|
-
}
|
|
224
|
-
nameToDisplayName(name) {
|
|
225
|
-
return name.split("-").map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
|
|
226
|
-
}
|
|
227
|
-
buildTags(name, displayName, props, slots, events) {
|
|
228
|
-
const tags = [name, displayName.toLowerCase()];
|
|
229
|
-
for (const prop of props.slice(0, 10)) {
|
|
230
|
-
tags.push(`prop:${prop}`);
|
|
231
|
-
}
|
|
232
|
-
for (const slot of slots.slice(0, 10)) {
|
|
233
|
-
tags.push(`slot:${slot}`);
|
|
234
|
-
}
|
|
235
|
-
for (const event of events.slice(0, 10)) {
|
|
236
|
-
tags.push(`event:${event}`);
|
|
237
|
-
}
|
|
238
|
-
return tags;
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
const _dirname = dirname(fileURLToPath(import.meta.url));
|
|
243
|
-
class DocumentationService {
|
|
244
|
-
docsRoot;
|
|
245
|
-
componentsDir;
|
|
246
|
-
generatedDocsDir;
|
|
247
|
-
guidesDir;
|
|
248
|
-
composablesDir;
|
|
249
|
-
directivesDir;
|
|
250
|
-
pluginsDir;
|
|
251
|
-
ecosystemDir;
|
|
252
|
-
utilsDir;
|
|
253
|
-
utilsTypesDir;
|
|
254
|
-
nodeDir;
|
|
255
|
-
iconsDir;
|
|
256
|
-
metadataExtractor = new MetadataExtractor();
|
|
257
|
-
constructor() {
|
|
258
|
-
const localDocsRoot = resolve(_dirname, "../docs/src");
|
|
259
|
-
const localGeneratedDocsDir = resolve(_dirname, "../docs/generated-docs");
|
|
260
|
-
this.docsRoot = localDocsRoot;
|
|
261
|
-
this.generatedDocsDir = localGeneratedDocsDir;
|
|
262
|
-
this.componentsDir = join(this.docsRoot, "components");
|
|
263
|
-
this.guidesDir = join(this.docsRoot, "guide");
|
|
264
|
-
this.composablesDir = join(this.docsRoot, "composables");
|
|
265
|
-
this.directivesDir = join(this.docsRoot, "directives");
|
|
266
|
-
this.pluginsDir = join(this.docsRoot, "plugins");
|
|
267
|
-
this.ecosystemDir = join(this.docsRoot, "ecosystem");
|
|
268
|
-
this.utilsDir = join(this.ecosystemDir, "utils");
|
|
269
|
-
this.utilsTypesDir = join(this.utilsDir, "types");
|
|
270
|
-
this.nodeDir = join(this.ecosystemDir, "node");
|
|
271
|
-
this.iconsDir = join(this.ecosystemDir, "icons");
|
|
272
|
-
}
|
|
273
|
-
pascalToKebabCase(pascalName) {
|
|
274
|
-
return pascalName.replace(/([A-Z])/g, "-$1").toLowerCase().replace(/^-/, "");
|
|
275
|
-
}
|
|
276
|
-
readMarkdownFile(filePath) {
|
|
277
|
-
try {
|
|
278
|
-
if (!existsSync(filePath)) {
|
|
279
|
-
return "";
|
|
280
|
-
}
|
|
281
|
-
return readFileSync(filePath, "utf-8");
|
|
282
|
-
} catch {
|
|
283
|
-
return "";
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
listMarkdownFiles(dirPath, options = {}) {
|
|
287
|
-
try {
|
|
288
|
-
if (!existsSync(dirPath)) {
|
|
289
|
-
return [];
|
|
290
|
-
}
|
|
291
|
-
const entries = readdirSync(dirPath);
|
|
292
|
-
return entries.filter((entry) => {
|
|
293
|
-
if (!entry.endsWith(".md"))
|
|
294
|
-
return false;
|
|
295
|
-
if (!options.keepIndex && entry === "index.md")
|
|
296
|
-
return false;
|
|
297
|
-
const fullPath = join(dirPath, entry);
|
|
298
|
-
return statSync(fullPath).isFile();
|
|
299
|
-
}).map((file) => file.replace(".md", "")).sort();
|
|
300
|
-
} catch {
|
|
301
|
-
return [];
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
// ========== COMPONENTS ==========
|
|
305
|
-
getComponentDocumentation(componentName) {
|
|
306
|
-
const kebabName = componentName.startsWith("Maz") ? this.pascalToKebabCase(componentName) : componentName;
|
|
307
|
-
const manualDocPath = join(this.componentsDir, `${kebabName}.md`);
|
|
308
|
-
const generatedDocPath = join(this.generatedDocsDir, `${kebabName}.doc.md`);
|
|
309
|
-
const [manualDoc, generatedDoc] = [
|
|
310
|
-
this.readMarkdownFile(manualDocPath),
|
|
311
|
-
this.readMarkdownFile(generatedDocPath)
|
|
312
|
-
];
|
|
313
|
-
if (!manualDoc && !generatedDoc) {
|
|
314
|
-
return "";
|
|
315
|
-
}
|
|
316
|
-
let combinedDoc = "";
|
|
317
|
-
if (manualDoc) {
|
|
318
|
-
combinedDoc += `${manualDoc}
|
|
319
|
-
|
|
320
|
-
`;
|
|
321
|
-
}
|
|
322
|
-
if (generatedDoc) {
|
|
323
|
-
combinedDoc += `---
|
|
324
|
-
|
|
325
|
-
# API Reference
|
|
326
|
-
|
|
327
|
-
${generatedDoc}`;
|
|
328
|
-
}
|
|
329
|
-
return combinedDoc.trim();
|
|
330
|
-
}
|
|
331
|
-
getAllComponents() {
|
|
332
|
-
const [manualFiles, generatedFiles] = [
|
|
333
|
-
this.listMarkdownFiles(this.componentsDir),
|
|
334
|
-
this.listMarkdownFiles(this.generatedDocsDir).map((file) => file.replace(".doc", ""))
|
|
335
|
-
];
|
|
336
|
-
const allComponents = /* @__PURE__ */ new Set([...manualFiles, ...generatedFiles]);
|
|
337
|
-
return Array.from(allComponents).sort();
|
|
338
|
-
}
|
|
339
|
-
// ========== GUIDES ==========
|
|
340
|
-
// Aggregates: guide/*.md + ecosystem/*.md (standalone) + ecosystem/icons/*.md (index.md → 'icons')
|
|
341
|
-
getGuideDocumentation(guideName) {
|
|
342
|
-
const candidates = [
|
|
343
|
-
join(this.guidesDir, `${guideName}.md`),
|
|
344
|
-
join(this.ecosystemDir, `${guideName}.md`),
|
|
345
|
-
join(this.iconsDir, `${guideName}.md`)
|
|
346
|
-
];
|
|
347
|
-
if (guideName === "icons") {
|
|
348
|
-
candidates.push(join(this.iconsDir, "index.md"));
|
|
349
|
-
}
|
|
350
|
-
for (const path of candidates) {
|
|
351
|
-
const content = this.readMarkdownFile(path);
|
|
352
|
-
if (content)
|
|
353
|
-
return content;
|
|
354
|
-
}
|
|
355
|
-
return "";
|
|
356
|
-
}
|
|
357
|
-
getAllGuides() {
|
|
358
|
-
const guides = /* @__PURE__ */ new Set();
|
|
359
|
-
for (const name of this.listMarkdownFiles(this.guidesDir)) {
|
|
360
|
-
guides.add(name);
|
|
361
|
-
}
|
|
362
|
-
for (const name of this.listMarkdownFiles(this.ecosystemDir)) {
|
|
363
|
-
guides.add(name);
|
|
364
|
-
}
|
|
365
|
-
for (const name of this.listMarkdownFiles(this.iconsDir)) {
|
|
366
|
-
guides.add(name);
|
|
367
|
-
}
|
|
368
|
-
if (existsSync(join(this.iconsDir, "index.md"))) {
|
|
369
|
-
guides.add("icons");
|
|
370
|
-
}
|
|
371
|
-
return Array.from(guides).sort();
|
|
372
|
-
}
|
|
373
|
-
// ========== COMPOSABLES ==========
|
|
374
|
-
getComposableDocumentation(composableName) {
|
|
375
|
-
const composablePath = join(this.composablesDir, `${composableName}.md`);
|
|
376
|
-
return this.readMarkdownFile(composablePath);
|
|
377
|
-
}
|
|
378
|
-
getAllComposables() {
|
|
379
|
-
return this.listMarkdownFiles(this.composablesDir);
|
|
380
|
-
}
|
|
381
|
-
// ========== DIRECTIVES ==========
|
|
382
|
-
getDirectiveDocumentation(directiveName) {
|
|
383
|
-
const directivePath = join(this.directivesDir, `${directiveName}.md`);
|
|
384
|
-
return this.readMarkdownFile(directivePath);
|
|
385
|
-
}
|
|
386
|
-
getAllDirectives() {
|
|
387
|
-
return this.listMarkdownFiles(this.directivesDir);
|
|
388
|
-
}
|
|
389
|
-
// ========== PLUGINS ==========
|
|
390
|
-
getPluginDocumentation(pluginName) {
|
|
391
|
-
const pluginPath = join(this.pluginsDir, `${pluginName}.md`);
|
|
392
|
-
return this.readMarkdownFile(pluginPath);
|
|
393
|
-
}
|
|
394
|
-
getAllPlugins() {
|
|
395
|
-
return this.listMarkdownFiles(this.pluginsDir);
|
|
396
|
-
}
|
|
397
|
-
// ========== UTILS ==========
|
|
398
|
-
// Aggregates: ecosystem/utils/*.md + ecosystem/utils/types/*.md
|
|
399
|
-
getUtilDocumentation(utilName) {
|
|
400
|
-
const candidates = [
|
|
401
|
-
join(this.utilsDir, `${utilName}.md`),
|
|
402
|
-
join(this.utilsTypesDir, `${utilName}.md`)
|
|
403
|
-
];
|
|
404
|
-
for (const path of candidates) {
|
|
405
|
-
const content = this.readMarkdownFile(path);
|
|
406
|
-
if (content)
|
|
407
|
-
return content;
|
|
408
|
-
}
|
|
409
|
-
return "";
|
|
410
|
-
}
|
|
411
|
-
getAllUtils() {
|
|
412
|
-
const utils = /* @__PURE__ */ new Set([
|
|
413
|
-
...this.listMarkdownFiles(this.utilsDir),
|
|
414
|
-
...this.listMarkdownFiles(this.utilsTypesDir)
|
|
415
|
-
]);
|
|
416
|
-
return Array.from(utils).sort();
|
|
417
|
-
}
|
|
418
|
-
// ========== NODE ==========
|
|
419
|
-
getNodeDocumentation(nodeName) {
|
|
420
|
-
const nodePath = join(this.nodeDir, `${nodeName}.md`);
|
|
421
|
-
return this.readMarkdownFile(nodePath);
|
|
422
|
-
}
|
|
423
|
-
getAllNode() {
|
|
424
|
-
return this.listMarkdownFiles(this.nodeDir);
|
|
425
|
-
}
|
|
426
|
-
// ========== UNIFIED LOADING ==========
|
|
427
|
-
getAllDocuments() {
|
|
428
|
-
const documents = [];
|
|
429
|
-
for (const name of this.getAllComponents()) {
|
|
430
|
-
const content = this.getComponentDocumentation(name);
|
|
431
|
-
if (content) {
|
|
432
|
-
documents.push(this.buildDocument(name, "component", content));
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
const categories = [
|
|
436
|
-
{ type: "guide", names: this.getAllGuides(), getContent: (name) => this.getGuideDocumentation(name) },
|
|
437
|
-
{ type: "composable", names: this.getAllComposables(), getContent: (name) => this.getComposableDocumentation(name) },
|
|
438
|
-
{ type: "directive", names: this.getAllDirectives(), getContent: (name) => this.getDirectiveDocumentation(name) },
|
|
439
|
-
{ type: "plugin", names: this.getAllPlugins(), getContent: (name) => this.getPluginDocumentation(name) },
|
|
440
|
-
{ type: "util", names: this.getAllUtils(), getContent: (name) => this.getUtilDocumentation(name) },
|
|
441
|
-
{ type: "node", names: this.getAllNode(), getContent: (name) => this.getNodeDocumentation(name) }
|
|
442
|
-
];
|
|
443
|
-
for (const category of categories) {
|
|
444
|
-
for (const name of category.names) {
|
|
445
|
-
const content = category.getContent(name);
|
|
446
|
-
if (content) {
|
|
447
|
-
documents.push(this.buildDocument(name, category.type, content));
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
return documents;
|
|
452
|
-
}
|
|
453
|
-
buildDocument(name, type, content) {
|
|
454
|
-
return {
|
|
455
|
-
name,
|
|
456
|
-
type,
|
|
457
|
-
content,
|
|
458
|
-
metadata: this.metadataExtractor.extract(name, type, content)
|
|
459
|
-
};
|
|
460
|
-
}
|
|
461
|
-
// ========== UTILITAIRES ==========
|
|
462
|
-
getOverview() {
|
|
463
|
-
const overviewPath = join(this.docsRoot, "index.md");
|
|
464
|
-
return this.readMarkdownFile(overviewPath);
|
|
465
|
-
}
|
|
466
|
-
searchDocumentation(query) {
|
|
467
|
-
const searchTerm = query.toLowerCase();
|
|
468
|
-
const results = [];
|
|
469
|
-
const buckets = [
|
|
470
|
-
{ type: "component", names: this.getAllComponents() },
|
|
471
|
-
{ type: "guide", names: this.getAllGuides() },
|
|
472
|
-
{ type: "composable", names: this.getAllComposables() },
|
|
473
|
-
{ type: "directive", names: this.getAllDirectives() },
|
|
474
|
-
{ type: "plugin", names: this.getAllPlugins() },
|
|
475
|
-
{ type: "util", names: this.getAllUtils() },
|
|
476
|
-
{ type: "node", names: this.getAllNode() }
|
|
477
|
-
];
|
|
478
|
-
for (const { type, names } of buckets) {
|
|
479
|
-
for (const name of names) {
|
|
480
|
-
if (name.toLowerCase().includes(searchTerm)) {
|
|
481
|
-
results.push(`${type}:${name}`);
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
return results;
|
|
486
|
-
}
|
|
487
|
-
getDiagnostics() {
|
|
488
|
-
const [components, guides, composables, directives, plugins, utils, nodeItems] = [
|
|
489
|
-
this.getAllComponents(),
|
|
490
|
-
this.getAllGuides(),
|
|
491
|
-
this.getAllComposables(),
|
|
492
|
-
this.getAllDirectives(),
|
|
493
|
-
this.getAllPlugins(),
|
|
494
|
-
this.getAllUtils(),
|
|
495
|
-
this.getAllNode()
|
|
496
|
-
];
|
|
497
|
-
let withManualDoc = 0;
|
|
498
|
-
let withGeneratedDoc = 0;
|
|
499
|
-
let withBothDocs = 0;
|
|
500
|
-
for (const component of components) {
|
|
501
|
-
const manualExists = existsSync(join(this.componentsDir, `${component}.md`));
|
|
502
|
-
const generatedExists = existsSync(join(this.generatedDocsDir, `${component}.doc.md`));
|
|
503
|
-
if (manualExists)
|
|
504
|
-
withManualDoc++;
|
|
505
|
-
if (generatedExists)
|
|
506
|
-
withGeneratedDoc++;
|
|
507
|
-
if (manualExists && generatedExists)
|
|
508
|
-
withBothDocs++;
|
|
509
|
-
}
|
|
510
|
-
return {
|
|
511
|
-
components: {
|
|
512
|
-
total: components.length,
|
|
513
|
-
withManualDoc,
|
|
514
|
-
withGeneratedDoc,
|
|
515
|
-
withBothDocs
|
|
516
|
-
},
|
|
517
|
-
guides: {
|
|
518
|
-
total: guides.length,
|
|
519
|
-
list: guides
|
|
520
|
-
},
|
|
521
|
-
composables: {
|
|
522
|
-
total: composables.length,
|
|
523
|
-
list: composables
|
|
524
|
-
},
|
|
525
|
-
directives: {
|
|
526
|
-
total: directives.length,
|
|
527
|
-
list: directives
|
|
528
|
-
},
|
|
529
|
-
plugins: {
|
|
530
|
-
total: plugins.length,
|
|
531
|
-
list: plugins
|
|
532
|
-
},
|
|
533
|
-
utils: {
|
|
534
|
-
total: utils.length,
|
|
535
|
-
list: utils
|
|
536
|
-
},
|
|
537
|
-
node: {
|
|
538
|
-
total: nodeItems.length,
|
|
539
|
-
list: nodeItems
|
|
540
|
-
},
|
|
541
|
-
paths: {
|
|
542
|
-
docsRoot: this.docsRoot,
|
|
543
|
-
componentsDir: this.componentsDir,
|
|
544
|
-
generatedDocsDir: this.generatedDocsDir,
|
|
545
|
-
guidesDir: this.guidesDir,
|
|
546
|
-
composablesDir: this.composablesDir,
|
|
547
|
-
directivesDir: this.directivesDir,
|
|
548
|
-
pluginsDir: this.pluginsDir,
|
|
549
|
-
ecosystemDir: this.ecosystemDir,
|
|
550
|
-
utilsDir: this.utilsDir,
|
|
551
|
-
nodeDir: this.nodeDir,
|
|
552
|
-
iconsDir: this.iconsDir
|
|
553
|
-
}
|
|
554
|
-
};
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
const SNIPPET_LENGTH = 150;
|
|
559
|
-
class SearchEngine {
|
|
560
|
-
documents = [];
|
|
561
|
-
invertedIndex = /* @__PURE__ */ new Map();
|
|
562
|
-
documentLengths = [];
|
|
563
|
-
buildIndex(documents) {
|
|
564
|
-
this.documents = documents;
|
|
565
|
-
this.invertedIndex.clear();
|
|
566
|
-
this.documentLengths = [];
|
|
567
|
-
for (let docIndex = 0; docIndex < documents.length; docIndex++) {
|
|
568
|
-
const tokens = this.tokenize(documents[docIndex].content);
|
|
569
|
-
this.documentLengths.push(tokens.length);
|
|
570
|
-
const termFrequencies = /* @__PURE__ */ new Map();
|
|
571
|
-
for (let pos = 0; pos < tokens.length; pos++) {
|
|
572
|
-
const token = tokens[pos];
|
|
573
|
-
const entry = termFrequencies.get(token);
|
|
574
|
-
if (entry) {
|
|
575
|
-
entry.count++;
|
|
576
|
-
entry.positions.push(pos);
|
|
577
|
-
} else {
|
|
578
|
-
termFrequencies.set(token, { count: 1, positions: [pos] });
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
for (const [term, { count, positions }] of termFrequencies) {
|
|
582
|
-
let postings = this.invertedIndex.get(term);
|
|
583
|
-
if (!postings) {
|
|
584
|
-
postings = [];
|
|
585
|
-
this.invertedIndex.set(term, postings);
|
|
586
|
-
}
|
|
587
|
-
postings.push({ docIndex, frequency: count, positions });
|
|
588
|
-
}
|
|
589
|
-
}
|
|
590
|
-
}
|
|
591
|
-
search(query, maxResults = 20) {
|
|
592
|
-
if (this.documents.length === 0 || !query.trim()) {
|
|
593
|
-
return [];
|
|
594
|
-
}
|
|
595
|
-
const exactPhrases = this.extractExactPhrases(query);
|
|
596
|
-
const remainingQuery = query.replace(/"[^"]*"/g, "").trim();
|
|
597
|
-
const singleTerms = remainingQuery ? this.tokenize(remainingQuery) : [];
|
|
598
|
-
const scores = /* @__PURE__ */ new Map();
|
|
599
|
-
const matchPositions = /* @__PURE__ */ new Map();
|
|
600
|
-
for (const term of singleTerms) {
|
|
601
|
-
this.scoreTerm(term, scores, matchPositions);
|
|
602
|
-
}
|
|
603
|
-
for (const phrase of exactPhrases) {
|
|
604
|
-
this.scorePhrase(phrase, scores, matchPositions);
|
|
605
|
-
}
|
|
606
|
-
return Array.from(scores.entries()).filter(([, score]) => score > 0).sort(([, a], [, b]) => b - a).slice(0, maxResults).map(([docIndex, score]) => {
|
|
607
|
-
const doc = this.documents[docIndex];
|
|
608
|
-
const positions = matchPositions.get(docIndex) ?? [];
|
|
609
|
-
return {
|
|
610
|
-
id: doc.id,
|
|
611
|
-
type: doc.type,
|
|
612
|
-
name: doc.name,
|
|
613
|
-
score: Math.round(score * 1e4) / 1e4,
|
|
614
|
-
snippet: this.extractSnippet(doc.content, positions)
|
|
615
|
-
};
|
|
616
|
-
});
|
|
617
|
-
}
|
|
618
|
-
getIndexedTermCount() {
|
|
619
|
-
return this.invertedIndex.size;
|
|
620
|
-
}
|
|
621
|
-
getDocumentCount() {
|
|
622
|
-
return this.documents.length;
|
|
623
|
-
}
|
|
624
|
-
scoreTerm(term, scores, matchPositions) {
|
|
625
|
-
const postings = this.invertedIndex.get(term);
|
|
626
|
-
if (!postings) {
|
|
627
|
-
return;
|
|
628
|
-
}
|
|
629
|
-
const totalDocs = this.documents.length;
|
|
630
|
-
const df = postings.length;
|
|
631
|
-
const idf = Math.log(1 + totalDocs / df);
|
|
632
|
-
for (const posting of postings) {
|
|
633
|
-
const docLength = this.documentLengths[posting.docIndex];
|
|
634
|
-
const tf = docLength > 0 ? posting.frequency / docLength : 0;
|
|
635
|
-
const tfidf = tf * idf;
|
|
636
|
-
scores.set(posting.docIndex, (scores.get(posting.docIndex) ?? 0) + tfidf);
|
|
637
|
-
const existing = matchPositions.get(posting.docIndex) ?? [];
|
|
638
|
-
existing.push(posting.positions[0]);
|
|
639
|
-
matchPositions.set(posting.docIndex, existing);
|
|
640
|
-
}
|
|
641
|
-
}
|
|
642
|
-
scorePhrase(phrase, scores, matchPositions) {
|
|
643
|
-
const phraseTokens = this.tokenize(phrase);
|
|
644
|
-
if (phraseTokens.length === 0) {
|
|
645
|
-
return;
|
|
646
|
-
}
|
|
647
|
-
const phraseMatches = this.findPhraseMatches(phraseTokens);
|
|
648
|
-
const matchedDocs = new Set(phraseMatches.map((m) => m.docIndex));
|
|
649
|
-
if (matchedDocs.size === 0) {
|
|
650
|
-
return;
|
|
651
|
-
}
|
|
652
|
-
const totalDocs = this.documents.length;
|
|
653
|
-
const idf = Math.log(1 + totalDocs / matchedDocs.size);
|
|
654
|
-
for (const docIndex of matchedDocs) {
|
|
655
|
-
const docMatches = phraseMatches.filter((m) => m.docIndex === docIndex);
|
|
656
|
-
const docLength = this.documentLengths[docIndex];
|
|
657
|
-
const tf = docLength > 0 ? docMatches.length / docLength : 0;
|
|
658
|
-
const tfidf = tf * idf * phraseTokens.length;
|
|
659
|
-
scores.set(docIndex, (scores.get(docIndex) ?? 0) + tfidf);
|
|
660
|
-
const existing = matchPositions.get(docIndex) ?? [];
|
|
661
|
-
existing.push(docMatches[0].position);
|
|
662
|
-
matchPositions.set(docIndex, existing);
|
|
663
|
-
}
|
|
664
|
-
}
|
|
665
|
-
findPhraseMatches(phraseTokens) {
|
|
666
|
-
const firstTermPostings = this.invertedIndex.get(phraseTokens[0]);
|
|
667
|
-
if (!firstTermPostings) {
|
|
668
|
-
return [];
|
|
669
|
-
}
|
|
670
|
-
const matches = [];
|
|
671
|
-
for (const posting of firstTermPostings) {
|
|
672
|
-
for (const startPos of posting.positions) {
|
|
673
|
-
if (this.isPhraseAtPosition(phraseTokens, posting.docIndex, startPos)) {
|
|
674
|
-
matches.push({ docIndex: posting.docIndex, position: startPos });
|
|
675
|
-
}
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
|
-
return matches;
|
|
679
|
-
}
|
|
680
|
-
isPhraseAtPosition(phraseTokens, docIndex, startPos) {
|
|
681
|
-
for (let i = 1; i < phraseTokens.length; i++) {
|
|
682
|
-
const nextPostings = this.invertedIndex.get(phraseTokens[i]);
|
|
683
|
-
if (!nextPostings) {
|
|
684
|
-
return false;
|
|
685
|
-
}
|
|
686
|
-
const nextPosting = nextPostings.find((p) => p.docIndex === docIndex);
|
|
687
|
-
if (!nextPosting || !nextPosting.positions.includes(startPos + i)) {
|
|
688
|
-
return false;
|
|
689
|
-
}
|
|
690
|
-
}
|
|
691
|
-
return true;
|
|
692
|
-
}
|
|
693
|
-
extractExactPhrases(query) {
|
|
694
|
-
const phrases = [];
|
|
695
|
-
const regex = /"([^"]+)"/g;
|
|
696
|
-
for (const match of query.matchAll(regex)) {
|
|
697
|
-
if (match[1].trim()) {
|
|
698
|
-
phrases.push(match[1].trim());
|
|
699
|
-
}
|
|
700
|
-
}
|
|
701
|
-
return phrases;
|
|
702
|
-
}
|
|
703
|
-
tokenize(text) {
|
|
704
|
-
return text.toLowerCase().replace(/[#*`|[\](){}!@$%^&+=~<>/\\,;:.?'"_-]+/g, " ").split(/\s+/).filter((token) => token.length > 1);
|
|
705
|
-
}
|
|
706
|
-
extractSnippet(content, tokenPositions) {
|
|
707
|
-
if (!content || tokenPositions.length === 0) {
|
|
708
|
-
return content.slice(0, SNIPPET_LENGTH).trim();
|
|
709
|
-
}
|
|
710
|
-
const tokens = this.tokenize(content);
|
|
711
|
-
if (tokens.length === 0) {
|
|
712
|
-
return content.slice(0, SNIPPET_LENGTH).trim();
|
|
713
|
-
}
|
|
714
|
-
const bestPosition = tokenPositions[0];
|
|
715
|
-
const targetToken = tokens[Math.min(bestPosition, tokens.length - 1)];
|
|
716
|
-
const contentLower = content.toLowerCase();
|
|
717
|
-
const charIndex = contentLower.indexOf(targetToken);
|
|
718
|
-
if (charIndex === -1) {
|
|
719
|
-
return content.slice(0, SNIPPET_LENGTH).trim();
|
|
720
|
-
}
|
|
721
|
-
const halfSnippet = Math.floor(SNIPPET_LENGTH / 2);
|
|
722
|
-
let start = Math.max(0, charIndex - halfSnippet);
|
|
723
|
-
let end = Math.min(content.length, start + SNIPPET_LENGTH);
|
|
724
|
-
if (end === content.length) {
|
|
725
|
-
start = Math.max(0, end - SNIPPET_LENGTH);
|
|
726
|
-
}
|
|
727
|
-
if (start > 0) {
|
|
728
|
-
const spaceIndex = content.indexOf(" ", start);
|
|
729
|
-
if (spaceIndex !== -1 && spaceIndex < start + 20) {
|
|
730
|
-
start = spaceIndex + 1;
|
|
731
|
-
}
|
|
732
|
-
}
|
|
733
|
-
if (end < content.length) {
|
|
734
|
-
const spaceIndex = content.lastIndexOf(" ", end);
|
|
735
|
-
if (spaceIndex !== -1 && spaceIndex > end - 20) {
|
|
736
|
-
end = spaceIndex;
|
|
737
|
-
}
|
|
738
|
-
}
|
|
739
|
-
let snippet = content.slice(start, end).trim();
|
|
740
|
-
if (start > 0) {
|
|
741
|
-
snippet = `...${snippet}`;
|
|
742
|
-
}
|
|
743
|
-
if (end < content.length) {
|
|
744
|
-
snippet = `${snippet}...`;
|
|
745
|
-
}
|
|
746
|
-
return snippet;
|
|
747
|
-
}
|
|
748
|
-
}
|
|
749
|
-
|
|
750
|
-
const NAME_BOOST = 3;
|
|
751
|
-
const TAG_BOOST = 2;
|
|
752
|
-
const CONTENT_BOOST = 1;
|
|
753
|
-
const DEFAULT_MAX_RESULTS = 10;
|
|
754
|
-
class UnifiedSearchService {
|
|
755
|
-
searchEngine = new SearchEngine();
|
|
756
|
-
documents = [];
|
|
757
|
-
initialize(documents) {
|
|
758
|
-
this.documents = documents;
|
|
759
|
-
this.searchEngine.buildIndex(
|
|
760
|
-
documents.map((doc) => ({
|
|
761
|
-
id: doc.name,
|
|
762
|
-
type: doc.type,
|
|
763
|
-
name: doc.name,
|
|
764
|
-
content: doc.content
|
|
765
|
-
}))
|
|
766
|
-
);
|
|
767
|
-
}
|
|
768
|
-
search(query, options = {}) {
|
|
769
|
-
const { category, maxResults = DEFAULT_MAX_RESULTS } = options;
|
|
770
|
-
if (!query.trim()) {
|
|
771
|
-
return [];
|
|
772
|
-
}
|
|
773
|
-
const normalizedQuery = query.toLowerCase().trim();
|
|
774
|
-
const queryTokens = this.searchEngine.tokenize(query);
|
|
775
|
-
let candidates = this.documents;
|
|
776
|
-
if (category) {
|
|
777
|
-
candidates = candidates.filter((doc) => doc.type === category);
|
|
778
|
-
}
|
|
779
|
-
const tfidfResults = this.searchEngine.search(query, candidates.length || this.documents.length);
|
|
780
|
-
const tfidfScoreMap = /* @__PURE__ */ new Map();
|
|
781
|
-
for (const result of tfidfResults) {
|
|
782
|
-
tfidfScoreMap.set(result.id, { score: result.score, snippet: result.snippet });
|
|
783
|
-
}
|
|
784
|
-
const scored = [];
|
|
785
|
-
for (const doc of candidates) {
|
|
786
|
-
const nameScore = this.scoreNameMatch(normalizedQuery, doc) * NAME_BOOST;
|
|
787
|
-
const tagScore = this.scoreTagMatch(normalizedQuery, queryTokens, doc) * TAG_BOOST;
|
|
788
|
-
const tfidfEntry = tfidfScoreMap.get(doc.name);
|
|
789
|
-
const contentScore = (tfidfEntry?.score ?? 0) * CONTENT_BOOST;
|
|
790
|
-
const totalScore = nameScore + tagScore + contentScore;
|
|
791
|
-
if (totalScore > 0) {
|
|
792
|
-
scored.push({
|
|
793
|
-
name: doc.name,
|
|
794
|
-
displayName: doc.metadata.displayName,
|
|
795
|
-
type: doc.type,
|
|
796
|
-
description: doc.metadata.description,
|
|
797
|
-
score: Math.round(totalScore * 1e4) / 1e4,
|
|
798
|
-
snippet: tfidfEntry?.snippet ?? doc.content.slice(0, 150).trim()
|
|
799
|
-
});
|
|
800
|
-
}
|
|
801
|
-
}
|
|
802
|
-
return scored.sort((a, b) => b.score - a.score).slice(0, maxResults);
|
|
803
|
-
}
|
|
804
|
-
scoreNameMatch(normalizedQuery, doc) {
|
|
805
|
-
const name = doc.name.toLowerCase();
|
|
806
|
-
const displayName = doc.metadata.displayName.toLowerCase();
|
|
807
|
-
if (name === normalizedQuery || displayName === normalizedQuery) {
|
|
808
|
-
return 1;
|
|
809
|
-
}
|
|
810
|
-
if (name.includes(normalizedQuery) || displayName.includes(normalizedQuery)) {
|
|
811
|
-
return 0.7;
|
|
812
|
-
}
|
|
813
|
-
if (normalizedQuery.includes(name)) {
|
|
814
|
-
return 0.5;
|
|
815
|
-
}
|
|
816
|
-
return 0;
|
|
817
|
-
}
|
|
818
|
-
scoreTagMatch(normalizedQuery, queryTokens, doc) {
|
|
819
|
-
const tags = doc.metadata.tags;
|
|
820
|
-
for (const tag of tags) {
|
|
821
|
-
if (tag === normalizedQuery) {
|
|
822
|
-
return 1;
|
|
823
|
-
}
|
|
824
|
-
}
|
|
825
|
-
if (queryTokens.length === 0) {
|
|
826
|
-
return 0;
|
|
827
|
-
}
|
|
828
|
-
let matchedTokens = 0;
|
|
829
|
-
for (const token of queryTokens) {
|
|
830
|
-
for (const tag of tags) {
|
|
831
|
-
if (tag.includes(token) || token.includes(tag)) {
|
|
832
|
-
matchedTokens++;
|
|
833
|
-
break;
|
|
834
|
-
}
|
|
835
|
-
}
|
|
836
|
-
}
|
|
837
|
-
return matchedTokens / queryTokens.length * 0.8;
|
|
838
|
-
}
|
|
839
|
-
}
|
|
840
|
-
|
|
841
|
-
class MazUiMcpServer {
|
|
842
|
-
server;
|
|
843
|
-
documentationService = new DocumentationService();
|
|
844
|
-
unifiedSearchService = new UnifiedSearchService();
|
|
845
|
-
documentationIndex = [];
|
|
846
|
-
constructor() {
|
|
847
|
-
this.server = new Server(
|
|
848
|
-
{
|
|
849
|
-
name: "maz-ui-mcp",
|
|
850
|
-
version
|
|
851
|
-
},
|
|
852
|
-
{
|
|
853
|
-
capabilities: {
|
|
854
|
-
resources: {},
|
|
855
|
-
tools: {}
|
|
856
|
-
}
|
|
857
|
-
}
|
|
858
|
-
);
|
|
859
|
-
this.buildDocumentationIndex();
|
|
860
|
-
this.setupHandlers();
|
|
861
|
-
}
|
|
862
|
-
getDocumentationService() {
|
|
863
|
-
return this.documentationService;
|
|
864
|
-
}
|
|
865
|
-
/**
|
|
866
|
-
* Build a comprehensive index of all available documentation
|
|
867
|
-
* This helps the AI understand what's available and how to access it
|
|
868
|
-
*/
|
|
869
|
-
buildDocumentationIndex() {
|
|
870
|
-
const index = [];
|
|
871
|
-
index.push({
|
|
872
|
-
type: "guide",
|
|
873
|
-
name: "overview",
|
|
874
|
-
displayName: "Library Overview",
|
|
875
|
-
description: "Complete overview and introduction to Maz-UI Vue.js component library",
|
|
876
|
-
tags: ["overview", "introduction", "getting-started", "maz-ui"],
|
|
877
|
-
uri: "overview://"
|
|
878
|
-
});
|
|
879
|
-
const components = this.documentationService.getAllComponents();
|
|
880
|
-
for (const component of components) {
|
|
881
|
-
const pascalName = component.split("-").map(
|
|
882
|
-
(part) => part.charAt(0).toUpperCase() + part.slice(1)
|
|
883
|
-
).join("");
|
|
884
|
-
const componentType = this.getComponentType(component);
|
|
885
|
-
const tags = [
|
|
886
|
-
"component",
|
|
887
|
-
"vue",
|
|
888
|
-
component,
|
|
889
|
-
pascalName.toLowerCase(),
|
|
890
|
-
componentType,
|
|
891
|
-
...this.generateSearchTags(component)
|
|
892
|
-
];
|
|
893
|
-
index.push({
|
|
894
|
-
type: "component",
|
|
895
|
-
name: component,
|
|
896
|
-
displayName: `${pascalName} Component`,
|
|
897
|
-
description: `Vue.js ${componentType} component: ${pascalName} - Interactive UI element with props, events, slots and styling options`,
|
|
898
|
-
tags,
|
|
899
|
-
uri: `component://${component}`
|
|
900
|
-
});
|
|
901
|
-
}
|
|
902
|
-
const guides = this.documentationService.getAllGuides();
|
|
903
|
-
for (const guide of guides) {
|
|
904
|
-
const displayName = guide.split("-").map(
|
|
905
|
-
(part) => part.charAt(0).toUpperCase() + part.slice(1)
|
|
906
|
-
).join(" ");
|
|
907
|
-
const tags = [
|
|
908
|
-
"guide",
|
|
909
|
-
"documentation",
|
|
910
|
-
guide,
|
|
911
|
-
displayName.toLowerCase(),
|
|
912
|
-
...this.generateSearchTags(guide)
|
|
913
|
-
];
|
|
914
|
-
index.push({
|
|
915
|
-
type: "guide",
|
|
916
|
-
name: guide,
|
|
917
|
-
displayName: `Guide: ${displayName}`,
|
|
918
|
-
description: `Documentation guide: ${displayName} - Setup instructions, configuration options, and best practices`,
|
|
919
|
-
tags,
|
|
920
|
-
uri: `guide://${guide}`
|
|
921
|
-
});
|
|
922
|
-
}
|
|
923
|
-
const composables = this.documentationService.getAllComposables();
|
|
924
|
-
for (const composable of composables) {
|
|
925
|
-
const tags = [
|
|
926
|
-
"composable",
|
|
927
|
-
"vue3",
|
|
928
|
-
"composition-api",
|
|
929
|
-
composable,
|
|
930
|
-
composable.replace("use", "").toLowerCase(),
|
|
931
|
-
...this.generateSearchTags(composable)
|
|
932
|
-
];
|
|
933
|
-
index.push({
|
|
934
|
-
type: "composable",
|
|
935
|
-
name: composable,
|
|
936
|
-
displayName: `${composable} Composable`,
|
|
937
|
-
description: `Vue 3 Composition API composable: ${composable} - Reactive state management and reusable logic`,
|
|
938
|
-
tags,
|
|
939
|
-
uri: `composable://${composable}`
|
|
940
|
-
});
|
|
941
|
-
}
|
|
942
|
-
const directives = this.documentationService.getAllDirectives();
|
|
943
|
-
for (const directive of directives) {
|
|
944
|
-
const tags = [
|
|
945
|
-
"directive",
|
|
946
|
-
"vue",
|
|
947
|
-
"dom",
|
|
948
|
-
directive,
|
|
949
|
-
`v-${directive}`,
|
|
950
|
-
...this.generateSearchTags(directive)
|
|
951
|
-
];
|
|
952
|
-
index.push({
|
|
953
|
-
type: "directive",
|
|
954
|
-
name: directive,
|
|
955
|
-
displayName: `v-${directive} Directive`,
|
|
956
|
-
description: `Vue directive: v-${directive} - DOM manipulation and behavioral enhancement for elements`,
|
|
957
|
-
tags,
|
|
958
|
-
uri: `directive://${directive}`
|
|
959
|
-
});
|
|
960
|
-
}
|
|
961
|
-
const plugins = this.documentationService.getAllPlugins();
|
|
962
|
-
for (const plugin of plugins) {
|
|
963
|
-
const tags = [
|
|
964
|
-
"plugin",
|
|
965
|
-
"vue",
|
|
966
|
-
"global",
|
|
967
|
-
plugin,
|
|
968
|
-
plugin.toLowerCase(),
|
|
969
|
-
...this.generateSearchTags(plugin)
|
|
970
|
-
];
|
|
971
|
-
index.push({
|
|
972
|
-
type: "plugin",
|
|
973
|
-
name: plugin,
|
|
974
|
-
displayName: `${plugin} Plugin`,
|
|
975
|
-
description: `Vue plugin: ${plugin} - Application-wide functionality and global services integration`,
|
|
976
|
-
tags,
|
|
977
|
-
uri: `plugin://${plugin}`
|
|
978
|
-
});
|
|
979
|
-
}
|
|
980
|
-
const utils = this.documentationService.getAllUtils();
|
|
981
|
-
for (const util of utils) {
|
|
982
|
-
const utilType = this.getUtilType(util);
|
|
983
|
-
const tags = [
|
|
984
|
-
"util",
|
|
985
|
-
"utility",
|
|
986
|
-
"function",
|
|
987
|
-
"maz-ui-utils",
|
|
988
|
-
util,
|
|
989
|
-
utilType,
|
|
990
|
-
...this.generateSearchTags(util)
|
|
991
|
-
];
|
|
992
|
-
index.push({
|
|
993
|
-
type: "util",
|
|
994
|
-
name: util,
|
|
995
|
-
displayName: `${util} Util`,
|
|
996
|
-
description: `Utility from @maz-ui/utils: ${util} - ${utilType} utility for data processing and manipulation`,
|
|
997
|
-
tags,
|
|
998
|
-
uri: `util://${util}`
|
|
999
|
-
});
|
|
1000
|
-
}
|
|
1001
|
-
const nodeItems = this.documentationService.getAllNode();
|
|
1002
|
-
for (const nodeItem of nodeItems) {
|
|
1003
|
-
const tags = [
|
|
1004
|
-
"node",
|
|
1005
|
-
"server",
|
|
1006
|
-
"cli",
|
|
1007
|
-
"maz-ui-node",
|
|
1008
|
-
nodeItem,
|
|
1009
|
-
...this.generateSearchTags(nodeItem)
|
|
1010
|
-
];
|
|
1011
|
-
index.push({
|
|
1012
|
-
type: "node",
|
|
1013
|
-
name: nodeItem,
|
|
1014
|
-
displayName: `${nodeItem} Node Utility`,
|
|
1015
|
-
description: `Node.js utility from @maz-ui/node: ${nodeItem} - server-side helper for scripts, CLI and SSR runtimes`,
|
|
1016
|
-
tags,
|
|
1017
|
-
uri: `node://${nodeItem}`
|
|
1018
|
-
});
|
|
1019
|
-
}
|
|
1020
|
-
this.documentationIndex = index;
|
|
1021
|
-
this.unifiedSearchService.initialize(this.documentationService.getAllDocuments());
|
|
1022
|
-
}
|
|
1023
|
-
/**
|
|
1024
|
-
* Generate additional search tags based on common patterns
|
|
1025
|
-
*/
|
|
1026
|
-
generateSearchTags(name) {
|
|
1027
|
-
const tags = [];
|
|
1028
|
-
const commonMappings = {
|
|
1029
|
-
btn: ["button"],
|
|
1030
|
-
input: ["form", "field"],
|
|
1031
|
-
select: ["dropdown", "option"],
|
|
1032
|
-
dialog: ["modal", "popup"],
|
|
1033
|
-
tooltip: ["hint", "tip"],
|
|
1034
|
-
toast: ["notification", "snackbar"],
|
|
1035
|
-
card: ["panel"],
|
|
1036
|
-
avatar: ["profile", "image"],
|
|
1037
|
-
badge: ["label", "tag"],
|
|
1038
|
-
spinner: ["loader", "loading"],
|
|
1039
|
-
divider: ["separator"],
|
|
1040
|
-
drawer: ["sidebar", "panel"],
|
|
1041
|
-
tabs: ["tab", "navigation"],
|
|
1042
|
-
accordion: ["collapse", "expand"],
|
|
1043
|
-
carousel: ["slider", "slideshow"],
|
|
1044
|
-
gallery: ["images", "photos"],
|
|
1045
|
-
stepper: ["steps", "wizard"],
|
|
1046
|
-
table: ["grid", "data"],
|
|
1047
|
-
chart: ["graph", "visualization"],
|
|
1048
|
-
date: ["calendar", "picker"],
|
|
1049
|
-
time: ["clock", "picker"]
|
|
1050
|
-
};
|
|
1051
|
-
for (const [key, aliases] of Object.entries(commonMappings)) {
|
|
1052
|
-
if (name.toLowerCase().includes(key)) {
|
|
1053
|
-
tags.push(...aliases);
|
|
1054
|
-
}
|
|
1055
|
-
}
|
|
1056
|
-
return tags;
|
|
1057
|
-
}
|
|
1058
|
-
/**
|
|
1059
|
-
* Determine component type for better categorization
|
|
1060
|
-
*/
|
|
1061
|
-
getComponentType(componentName) {
|
|
1062
|
-
const formComponents = ["btn", "checkbox", "checklist", "date", "input", "radio", "select", "slider", "switch", "textarea"];
|
|
1063
|
-
const layoutComponents = ["accordion", "card"];
|
|
1064
|
-
const navigationComponents = ["tabs", "stepper", "pagination", "link", "pull", "reading"];
|
|
1065
|
-
const overlayComponents = ["dialog", "drawer", "sheet", "popover", "dropdown", "backdrop"];
|
|
1066
|
-
const dataComponents = ["chart", "table", "dropzone"];
|
|
1067
|
-
const feedbackComponents = ["spinner", "loading", "progress", "badge"];
|
|
1068
|
-
const displayComponents = ["avatar", "gallery", "lazy", "carousel", "icon"];
|
|
1069
|
-
const animationComponents = ["animated", "expand"];
|
|
1070
|
-
const lowerName = componentName.toLowerCase();
|
|
1071
|
-
if (formComponents.some((type) => lowerName.includes(type)))
|
|
1072
|
-
return "form";
|
|
1073
|
-
if (layoutComponents.some((type) => lowerName.includes(type)))
|
|
1074
|
-
return "layout";
|
|
1075
|
-
if (navigationComponents.some((type) => lowerName.includes(type)))
|
|
1076
|
-
return "navigation";
|
|
1077
|
-
if (overlayComponents.some((type) => lowerName.includes(type)))
|
|
1078
|
-
return "overlay";
|
|
1079
|
-
if (dataComponents.some((type) => lowerName.includes(type)))
|
|
1080
|
-
return "data";
|
|
1081
|
-
if (feedbackComponents.some((type) => lowerName.includes(type)))
|
|
1082
|
-
return "feedback";
|
|
1083
|
-
if (displayComponents.some((type) => lowerName.includes(type)))
|
|
1084
|
-
return "display";
|
|
1085
|
-
if (animationComponents.some((type) => lowerName.includes(type)))
|
|
1086
|
-
return "animation";
|
|
1087
|
-
return "general";
|
|
1088
|
-
}
|
|
1089
|
-
/**
|
|
1090
|
-
* Determine util type for better categorization
|
|
1091
|
-
*/
|
|
1092
|
-
getUtilType(utilName) {
|
|
1093
|
-
const lowerName = utilName.toLowerCase();
|
|
1094
|
-
if (lowerName.includes("string") || lowerName.includes("text"))
|
|
1095
|
-
return "string";
|
|
1096
|
-
if (lowerName.includes("date") || lowerName.includes("time"))
|
|
1097
|
-
return "date";
|
|
1098
|
-
if (lowerName.includes("number") || lowerName.includes("currency"))
|
|
1099
|
-
return "number";
|
|
1100
|
-
if (lowerName.includes("color") || lowerName.includes("theme"))
|
|
1101
|
-
return "color";
|
|
1102
|
-
if (lowerName.includes("format") || lowerName.includes("parse"))
|
|
1103
|
-
return "formatting";
|
|
1104
|
-
if (lowerName.includes("valid") || lowerName.includes("check"))
|
|
1105
|
-
return "validation";
|
|
1106
|
-
return "general";
|
|
1107
|
-
}
|
|
1108
|
-
/**
|
|
1109
|
-
* Resolve a document name using intelligent matching:
|
|
1110
|
-
* PascalCase (MazBtn), kebab-case (maz-btn), short name (btn), aliases
|
|
1111
|
-
*/
|
|
1112
|
-
resolveDocumentName(name, type) {
|
|
1113
|
-
const normalizedName = name.toLowerCase().trim();
|
|
1114
|
-
const candidates = type && type !== "auto" ? this.documentationIndex.filter((item) => item.type === type) : this.documentationIndex;
|
|
1115
|
-
const exactMatch = candidates.find((item) => item.name.toLowerCase() === normalizedName);
|
|
1116
|
-
if (exactMatch) {
|
|
1117
|
-
return exactMatch;
|
|
1118
|
-
}
|
|
1119
|
-
if (/[A-Z]/.test(name)) {
|
|
1120
|
-
const kebabName = name.replace(/([A-Z])/g, "-$1").toLowerCase().replace(/^-/, "");
|
|
1121
|
-
const kebabMatch = candidates.find((item) => item.name.toLowerCase() === kebabName);
|
|
1122
|
-
if (kebabMatch) {
|
|
1123
|
-
return kebabMatch;
|
|
1124
|
-
}
|
|
1125
|
-
}
|
|
1126
|
-
if (!normalizedName.startsWith("maz-")) {
|
|
1127
|
-
const prefixedName = `maz-${normalizedName}`;
|
|
1128
|
-
const prefixMatch = candidates.find((item) => item.name.toLowerCase() === prefixedName);
|
|
1129
|
-
if (prefixMatch) {
|
|
1130
|
-
return prefixMatch;
|
|
1131
|
-
}
|
|
1132
|
-
}
|
|
1133
|
-
const displayMatch = candidates.find(
|
|
1134
|
-
(item) => item.displayName.toLowerCase() === normalizedName
|
|
1135
|
-
);
|
|
1136
|
-
if (displayMatch) {
|
|
1137
|
-
return displayMatch;
|
|
1138
|
-
}
|
|
1139
|
-
const tagMatch = candidates.find(
|
|
1140
|
-
(item) => item.tags.some((tag) => tag.toLowerCase() === normalizedName)
|
|
1141
|
-
);
|
|
1142
|
-
if (tagMatch) {
|
|
1143
|
-
return tagMatch;
|
|
1144
|
-
}
|
|
1145
|
-
const partialMatch = candidates.find(
|
|
1146
|
-
(item) => item.name.toLowerCase().includes(normalizedName) || item.displayName.toLowerCase().includes(normalizedName)
|
|
1147
|
-
);
|
|
1148
|
-
if (partialMatch) {
|
|
1149
|
-
return partialMatch;
|
|
1150
|
-
}
|
|
1151
|
-
return void 0;
|
|
1152
|
-
}
|
|
1153
|
-
handleSearch(args) {
|
|
1154
|
-
const query = args?.query;
|
|
1155
|
-
const category = args?.category;
|
|
1156
|
-
const maxResults = args?.maxResults || 10;
|
|
1157
|
-
if (!query) {
|
|
1158
|
-
throw new Error("Search query is required. Provide a component name, description, prop name, or use case.");
|
|
1159
|
-
}
|
|
1160
|
-
const results = this.unifiedSearchService.search(query, {
|
|
1161
|
-
category,
|
|
1162
|
-
maxResults
|
|
1163
|
-
});
|
|
1164
|
-
if (results.length === 0) {
|
|
1165
|
-
return {
|
|
1166
|
-
content: [{
|
|
1167
|
-
type: "text",
|
|
1168
|
-
text: `No results found for "${query}".${category ? ` (filtered by category: ${category})` : ""}
|
|
1169
|
-
|
|
1170
|
-
**Suggestions:**
|
|
1171
|
-
- Try broader or different terms (e.g. "button" instead of "btn")
|
|
1172
|
-
- Remove the category filter to search all documentation
|
|
1173
|
-
- Use \`list\` to browse all available documentation`
|
|
1174
|
-
}]
|
|
1175
|
-
};
|
|
1176
|
-
}
|
|
1177
|
-
let resultText = `# Search Results for "${query}" (${results.length} found)
|
|
1178
|
-
|
|
1179
|
-
`;
|
|
1180
|
-
for (const item of results) {
|
|
1181
|
-
resultText += `## ${item.displayName}
|
|
1182
|
-
`;
|
|
1183
|
-
resultText += `- **Name**: \`${item.name}\`
|
|
1184
|
-
`;
|
|
1185
|
-
resultText += `- **Type**: ${item.type}
|
|
1186
|
-
`;
|
|
1187
|
-
resultText += `- **Description**: ${item.description}
|
|
1188
|
-
`;
|
|
1189
|
-
resultText += `- **Score**: ${item.score}
|
|
1190
|
-
`;
|
|
1191
|
-
resultText += `- **Snippet**: ${item.snippet}
|
|
1192
|
-
`;
|
|
1193
|
-
resultText += `- **Get full doc**: Use \`get_doc\` with name \`${item.name}\`
|
|
1194
|
-
|
|
1195
|
-
`;
|
|
1196
|
-
}
|
|
1197
|
-
return {
|
|
1198
|
-
content: [{
|
|
1199
|
-
type: "text",
|
|
1200
|
-
text: resultText
|
|
1201
|
-
}]
|
|
1202
|
-
};
|
|
1203
|
-
}
|
|
1204
|
-
handleList(args) {
|
|
1205
|
-
const category = args?.category || "all";
|
|
1206
|
-
const filteredIndex = category === "all" ? this.documentationIndex : this.documentationIndex.filter((item) => item.type === category);
|
|
1207
|
-
const groupedDocs = filteredIndex.reduce((acc, item) => {
|
|
1208
|
-
if (!acc[item.type])
|
|
1209
|
-
acc[item.type] = [];
|
|
1210
|
-
acc[item.type].push(item);
|
|
1211
|
-
return acc;
|
|
1212
|
-
}, {});
|
|
1213
|
-
const typeLabels = {
|
|
1214
|
-
component: "Components",
|
|
1215
|
-
guide: "Guides",
|
|
1216
|
-
composable: "Composables",
|
|
1217
|
-
directive: "Directives",
|
|
1218
|
-
plugin: "Plugins",
|
|
1219
|
-
util: "Utils",
|
|
1220
|
-
node: "Node Utilities"
|
|
1221
|
-
};
|
|
1222
|
-
const typeOrder = ["component", "guide", "composable", "directive", "plugin", "util", "node"];
|
|
1223
|
-
let result = `# Maz-UI Documentation (${filteredIndex.length} items)
|
|
1224
|
-
|
|
1225
|
-
`;
|
|
1226
|
-
for (const type of typeOrder) {
|
|
1227
|
-
if (!groupedDocs[type])
|
|
1228
|
-
continue;
|
|
1229
|
-
const items = groupedDocs[type].sort((a, b) => a.name.localeCompare(b.name));
|
|
1230
|
-
result += `## ${typeLabels[type]} (${items.length})
|
|
1231
|
-
|
|
1232
|
-
`;
|
|
1233
|
-
for (const item of items) {
|
|
1234
|
-
result += `- **${item.displayName}** (\`${item.name}\`) \u2014 ${item.description}
|
|
1235
|
-
`;
|
|
1236
|
-
}
|
|
1237
|
-
result += "\n";
|
|
1238
|
-
}
|
|
1239
|
-
return {
|
|
1240
|
-
content: [{
|
|
1241
|
-
type: "text",
|
|
1242
|
-
text: result.trim()
|
|
1243
|
-
}]
|
|
1244
|
-
};
|
|
1245
|
-
}
|
|
1246
|
-
handleGetDoc(args) {
|
|
1247
|
-
const docName = args?.name;
|
|
1248
|
-
const docType = args?.type || "auto";
|
|
1249
|
-
if (!docName) {
|
|
1250
|
-
throw new Error("Name is required");
|
|
1251
|
-
}
|
|
1252
|
-
const found = this.resolveDocumentName(docName, docType);
|
|
1253
|
-
if (!found) {
|
|
1254
|
-
return this.handleDocNotFound(docName);
|
|
1255
|
-
}
|
|
1256
|
-
const content = this.getDocumentContent(found);
|
|
1257
|
-
if (!content) {
|
|
1258
|
-
return {
|
|
1259
|
-
content: [{
|
|
1260
|
-
type: "text",
|
|
1261
|
-
text: `Found "${found.displayName}" but documentation content is not available. This might be a documentation file that needs to be created.`
|
|
1262
|
-
}]
|
|
1263
|
-
};
|
|
1264
|
-
}
|
|
1265
|
-
return {
|
|
1266
|
-
content: [{
|
|
1267
|
-
type: "text",
|
|
1268
|
-
text: content
|
|
1269
|
-
}]
|
|
1270
|
-
};
|
|
1271
|
-
}
|
|
1272
|
-
handleDocNotFound(docName) {
|
|
1273
|
-
const searchResults = this.unifiedSearchService.search(docName, { maxResults: 3 });
|
|
1274
|
-
if (searchResults.length === 0) {
|
|
1275
|
-
return {
|
|
1276
|
-
content: [{
|
|
1277
|
-
type: "text",
|
|
1278
|
-
text: `Documentation not found for "${docName}".
|
|
1279
|
-
|
|
1280
|
-
**Available options:**
|
|
1281
|
-
- Use \`search\` to find similar items
|
|
1282
|
-
- Use \`list\` to see all available documentation`
|
|
1283
|
-
}]
|
|
1284
|
-
};
|
|
1285
|
-
}
|
|
1286
|
-
const suggestions = searchResults.map((item) => `- **${item.displayName}** (\`${item.name}\`) - ${item.description}`).join("\n");
|
|
1287
|
-
return {
|
|
1288
|
-
content: [{
|
|
1289
|
-
type: "text",
|
|
1290
|
-
text: `Exact match not found for "${docName}". Did you mean:
|
|
1291
|
-
|
|
1292
|
-
${suggestions}
|
|
1293
|
-
|
|
1294
|
-
**Use \`get_doc\` with the exact name from above.**`
|
|
1295
|
-
}]
|
|
1296
|
-
};
|
|
1297
|
-
}
|
|
1298
|
-
getDocumentContent(doc) {
|
|
1299
|
-
const contentMethods = {
|
|
1300
|
-
component: (name) => this.documentationService.getComponentDocumentation(name),
|
|
1301
|
-
guide: (name) => this.documentationService.getGuideDocumentation(name),
|
|
1302
|
-
composable: (name) => this.documentationService.getComposableDocumentation(name),
|
|
1303
|
-
directive: (name) => this.documentationService.getDirectiveDocumentation(name),
|
|
1304
|
-
plugin: (name) => this.documentationService.getPluginDocumentation(name),
|
|
1305
|
-
util: (name) => this.documentationService.getUtilDocumentation(name),
|
|
1306
|
-
node: (name) => this.documentationService.getNodeDocumentation(name)
|
|
1307
|
-
};
|
|
1308
|
-
const getContent = contentMethods[doc.type];
|
|
1309
|
-
return getContent ? getContent(doc.name) : "";
|
|
1310
|
-
}
|
|
1311
|
-
setupHandlers() {
|
|
1312
|
-
this.server.setRequestHandler(ListResourcesRequestSchema, () => {
|
|
1313
|
-
return {
|
|
1314
|
-
resources: this.documentationIndex.map((item) => ({
|
|
1315
|
-
uri: item.uri,
|
|
1316
|
-
name: item.displayName,
|
|
1317
|
-
description: item.description,
|
|
1318
|
-
mimeType: "text/markdown"
|
|
1319
|
-
}))
|
|
1320
|
-
};
|
|
1321
|
-
});
|
|
1322
|
-
this.server.setRequestHandler(ReadResourceRequestSchema, (request) => {
|
|
1323
|
-
const { uri } = request.params;
|
|
1324
|
-
if (!uri) {
|
|
1325
|
-
throw new Error("URI is required");
|
|
1326
|
-
}
|
|
1327
|
-
let type, name;
|
|
1328
|
-
if (uri === "overview://") {
|
|
1329
|
-
type = "overview";
|
|
1330
|
-
name = "";
|
|
1331
|
-
} else if (uri.includes("://")) {
|
|
1332
|
-
[type, name] = uri.split("://");
|
|
1333
|
-
} else {
|
|
1334
|
-
throw new Error("Invalid URI format. Expected format: type://name");
|
|
1335
|
-
}
|
|
1336
|
-
if (!name && type !== "overview") {
|
|
1337
|
-
throw new Error("Resource name is required");
|
|
1338
|
-
}
|
|
1339
|
-
let content;
|
|
1340
|
-
try {
|
|
1341
|
-
switch (type) {
|
|
1342
|
-
case "overview":
|
|
1343
|
-
content = this.documentationService.getOverview();
|
|
1344
|
-
if (!content) {
|
|
1345
|
-
const diagnostics = this.documentationService.getDiagnostics();
|
|
1346
|
-
content = `# Maz-UI Vue.js Component Library
|
|
1347
|
-
|
|
1348
|
-
## Quick Stats
|
|
1349
|
-
- **${diagnostics.components.total} Components** - Ready-to-use Vue components
|
|
1350
|
-
- **${diagnostics.composables.total} Composables** - Vue 3 reactive utilities
|
|
1351
|
-
- **${diagnostics.directives.total} Directives** - DOM helpers
|
|
1352
|
-
- **${diagnostics.plugins.total} Plugins** - App-wide services
|
|
1353
|
-
- **${diagnostics.utils.total} Utils** - Utility functions from @maz-ui/utils
|
|
1354
|
-
- **${diagnostics.node.total} Node Utilities** - Server-side helpers from @maz-ui/node
|
|
1355
|
-
- **${diagnostics.guides.total} Guides** - Documentation
|
|
1356
|
-
|
|
1357
|
-
## Getting Started
|
|
1358
|
-
Use the MCP tools to explore components and features:
|
|
1359
|
-
- \`list\` - See everything available
|
|
1360
|
-
- \`search\` - Find specific features
|
|
1361
|
-
- \`get_doc\` - Get detailed documentation`;
|
|
1362
|
-
}
|
|
1363
|
-
break;
|
|
1364
|
-
case "component":
|
|
1365
|
-
content = this.documentationService.getComponentDocumentation(name);
|
|
1366
|
-
break;
|
|
1367
|
-
case "guide":
|
|
1368
|
-
content = this.documentationService.getGuideDocumentation(name);
|
|
1369
|
-
break;
|
|
1370
|
-
case "composable":
|
|
1371
|
-
content = this.documentationService.getComposableDocumentation(name);
|
|
1372
|
-
break;
|
|
1373
|
-
case "directive":
|
|
1374
|
-
content = this.documentationService.getDirectiveDocumentation(name);
|
|
1375
|
-
break;
|
|
1376
|
-
case "plugin":
|
|
1377
|
-
content = this.documentationService.getPluginDocumentation(name);
|
|
1378
|
-
break;
|
|
1379
|
-
case "util":
|
|
1380
|
-
content = this.documentationService.getUtilDocumentation(name);
|
|
1381
|
-
break;
|
|
1382
|
-
case "node":
|
|
1383
|
-
content = this.documentationService.getNodeDocumentation(name);
|
|
1384
|
-
break;
|
|
1385
|
-
default:
|
|
1386
|
-
throw new Error(`Unknown resource type: ${type}. Valid types: overview, component, guide, composable, directive, plugin, util, node`);
|
|
1387
|
-
}
|
|
1388
|
-
if (!content) {
|
|
1389
|
-
throw new Error(`Documentation not found for ${type}: ${name}`);
|
|
1390
|
-
}
|
|
1391
|
-
return {
|
|
1392
|
-
contents: [{
|
|
1393
|
-
uri,
|
|
1394
|
-
mimeType: "text/markdown",
|
|
1395
|
-
text: content
|
|
1396
|
-
}]
|
|
1397
|
-
};
|
|
1398
|
-
} catch (error) {
|
|
1399
|
-
throw new Error(`Failed to read ${type} documentation for "${name}": ${getErrorMessage(error)}`, { cause: error });
|
|
1400
|
-
}
|
|
1401
|
-
});
|
|
1402
|
-
this.server.setRequestHandler(ListToolsRequestSchema, () => {
|
|
1403
|
-
return {
|
|
1404
|
-
tools: [
|
|
1405
|
-
{
|
|
1406
|
-
name: "search",
|
|
1407
|
-
description: 'Search across ALL Maz-UI documentation using a powerful unified search engine. Combines exact name matching, tag/alias matching, and full-text content search with TF-IDF scoring. Use this tool for any search query: component names (e.g. "MazBtn"), functional descriptions (e.g. "date picker"), prop names (e.g. "model-value"), use cases (e.g. "form validation"), or aliases (e.g. "modal" for dialog). Returns ranked results with contextual snippets.',
|
|
1408
|
-
inputSchema: {
|
|
1409
|
-
type: "object",
|
|
1410
|
-
properties: {
|
|
1411
|
-
query: {
|
|
1412
|
-
type: "string",
|
|
1413
|
-
description: 'Search query \u2014 can be a component name, description, prop name, use case, or alias. Examples: "button", "MazDialog", "model-value", "phone number input", "lazy loading"'
|
|
1414
|
-
},
|
|
1415
|
-
category: {
|
|
1416
|
-
type: "string",
|
|
1417
|
-
enum: ["component", "guide", "composable", "directive", "plugin", "util", "node"],
|
|
1418
|
-
description: "Optional filter to restrict results to a specific documentation category"
|
|
1419
|
-
},
|
|
1420
|
-
maxResults: {
|
|
1421
|
-
type: "number",
|
|
1422
|
-
description: "Maximum number of results to return (default: 10)",
|
|
1423
|
-
default: 10,
|
|
1424
|
-
minimum: 1,
|
|
1425
|
-
maximum: 50
|
|
1426
|
-
}
|
|
1427
|
-
},
|
|
1428
|
-
required: ["query"]
|
|
1429
|
-
}
|
|
1430
|
-
},
|
|
1431
|
-
{
|
|
1432
|
-
name: "get_doc",
|
|
1433
|
-
description: "Get the complete documentation for a specific item. Supports exact names and common aliases. If the exact name isn't found, provides intelligent suggestions based on fuzzy matching.",
|
|
1434
|
-
inputSchema: {
|
|
1435
|
-
type: "object",
|
|
1436
|
-
properties: {
|
|
1437
|
-
name: {
|
|
1438
|
-
type: "string",
|
|
1439
|
-
description: 'Exact name or common alias. Examples: "maz-btn" or "MazBtn" for components, "useToast" for composables, "tooltip" for directives'
|
|
1440
|
-
},
|
|
1441
|
-
type: {
|
|
1442
|
-
type: "string",
|
|
1443
|
-
enum: ["auto", "component", "guide", "composable", "directive", "plugin", "util", "node"],
|
|
1444
|
-
description: 'Type hint to improve search accuracy (optional). Use "auto" to search all types.',
|
|
1445
|
-
default: "auto"
|
|
1446
|
-
}
|
|
1447
|
-
},
|
|
1448
|
-
required: ["name"]
|
|
1449
|
-
}
|
|
1450
|
-
},
|
|
1451
|
-
{
|
|
1452
|
-
name: "list",
|
|
1453
|
-
description: "Browse all available Maz-UI documentation grouped by category. Returns a structured list with counters per category and for each item: name, displayName, description. Use this tool to discover what components, composables, directives, plugins, utils, node utilities and guides are available. Examples: list all docs, list only components, list composables.",
|
|
1454
|
-
inputSchema: {
|
|
1455
|
-
type: "object",
|
|
1456
|
-
properties: {
|
|
1457
|
-
category: {
|
|
1458
|
-
type: "string",
|
|
1459
|
-
enum: ["all", "component", "guide", "composable", "directive", "plugin", "util", "node"],
|
|
1460
|
-
description: 'Filter by documentation category. Use "all" or omit to see everything.',
|
|
1461
|
-
default: "all"
|
|
1462
|
-
}
|
|
1463
|
-
}
|
|
1464
|
-
}
|
|
1465
|
-
}
|
|
1466
|
-
]
|
|
1467
|
-
};
|
|
1468
|
-
});
|
|
1469
|
-
this.server.setRequestHandler(CallToolRequestSchema, (request) => {
|
|
1470
|
-
const { name, arguments: args } = request.params;
|
|
1471
|
-
try {
|
|
1472
|
-
switch (name) {
|
|
1473
|
-
case "search":
|
|
1474
|
-
return this.handleSearch(args);
|
|
1475
|
-
case "list":
|
|
1476
|
-
return this.handleList(args);
|
|
1477
|
-
case "get_doc":
|
|
1478
|
-
return this.handleGetDoc(args);
|
|
1479
|
-
default:
|
|
1480
|
-
throw new Error(`Unknown tool: ${name}. Available tools: search, get_doc, list`);
|
|
1481
|
-
}
|
|
1482
|
-
} catch (error) {
|
|
1483
|
-
return {
|
|
1484
|
-
content: [{
|
|
1485
|
-
type: "text",
|
|
1486
|
-
text: `Error: ${getErrorMessage(error)}
|
|
1487
|
-
|
|
1488
|
-
**Available tools:**
|
|
1489
|
-
- \`search\` - Search across all documentation
|
|
1490
|
-
- \`get_doc\` - Get specific documentation
|
|
1491
|
-
- \`list\` - Browse all available documentation`
|
|
1492
|
-
}],
|
|
1493
|
-
isError: true
|
|
1494
|
-
};
|
|
1495
|
-
}
|
|
1496
|
-
});
|
|
1497
|
-
}
|
|
1498
|
-
async run() {
|
|
1499
|
-
const transport = new StdioServerTransport();
|
|
1500
|
-
await this.server.connect(transport);
|
|
1501
|
-
}
|
|
1502
|
-
}
|
|
1503
|
-
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
1504
|
-
const server = new MazUiMcpServer();
|
|
1505
|
-
server.run().catch((error) => {
|
|
1506
|
-
console.error("Failed to start MCP server:", getErrorMessage(error));
|
|
1507
|
-
process.exit(1);
|
|
1508
|
-
});
|
|
1509
|
-
}
|
|
1510
|
-
|
|
1511
|
-
export { MazUiMcpServer };
|