@mindfiredigital/ignix-lite-mcp 1.2.0 → 1.4.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.
Files changed (90) hide show
  1. package/README.md +108 -0
  2. package/dist/server.js +187 -1954
  3. package/dist/server.js.map +1 -1
  4. package/dist/utils/check-api.js +2 -0
  5. package/dist/utils/check-api.js.map +1 -1
  6. package/package.json +14 -6
  7. package/.turbo/turbo-build.log +0 -25
  8. package/CHANGELOG.md +0 -7
  9. package/dist/manifests/accordion.json +0 -61
  10. package/dist/manifests/alert.json +0 -69
  11. package/dist/manifests/avatar.json +0 -75
  12. package/dist/manifests/badge.json +0 -74
  13. package/dist/manifests/breadcrumb.json +0 -87
  14. package/dist/manifests/button.json +0 -85
  15. package/dist/manifests/card.json +0 -91
  16. package/dist/manifests/checkbox.json +0 -122
  17. package/dist/manifests/codeblock.json +0 -63
  18. package/dist/manifests/combobox.json +0 -33
  19. package/dist/manifests/dialog.json +0 -64
  20. package/dist/manifests/divider.json +0 -47
  21. package/dist/manifests/dropdown.json +0 -105
  22. package/dist/manifests/form.json +0 -81
  23. package/dist/manifests/grid.json +0 -143
  24. package/dist/manifests/input.json +0 -99
  25. package/dist/manifests/meter.json +0 -103
  26. package/dist/manifests/navigation.json +0 -70
  27. package/dist/manifests/progress.json +0 -88
  28. package/dist/manifests/radio.json +0 -121
  29. package/dist/manifests/select.json +0 -109
  30. package/dist/manifests/skeleton.json +0 -101
  31. package/dist/manifests/tab.json +0 -88
  32. package/dist/manifests/table.json +0 -92
  33. package/dist/manifests/textarea.json +0 -117
  34. package/dist/manifests/toast.json +0 -157
  35. package/dist/manifests/tooltip.json +0 -115
  36. package/dist/vector-index.json +0 -14015
  37. package/src/context/api-context.ts +0 -14
  38. package/src/global.d.ts +0 -15
  39. package/src/manifests/accordion.json +0 -61
  40. package/src/manifests/alert.json +0 -69
  41. package/src/manifests/avatar.json +0 -75
  42. package/src/manifests/badge.json +0 -74
  43. package/src/manifests/breadcrumb.json +0 -87
  44. package/src/manifests/button.json +0 -85
  45. package/src/manifests/card.json +0 -91
  46. package/src/manifests/checkbox.json +0 -122
  47. package/src/manifests/codeblock.json +0 -63
  48. package/src/manifests/combobox.json +0 -33
  49. package/src/manifests/dialog.json +0 -64
  50. package/src/manifests/divider.json +0 -47
  51. package/src/manifests/dropdown.json +0 -105
  52. package/src/manifests/form.json +0 -81
  53. package/src/manifests/grid.json +0 -143
  54. package/src/manifests/index.ts +0 -45
  55. package/src/manifests/input.json +0 -99
  56. package/src/manifests/meter.json +0 -103
  57. package/src/manifests/navigation.json +0 -70
  58. package/src/manifests/progress.json +0 -88
  59. package/src/manifests/radio.json +0 -121
  60. package/src/manifests/select.json +0 -109
  61. package/src/manifests/skeleton.json +0 -101
  62. package/src/manifests/tab.json +0 -88
  63. package/src/manifests/table.json +0 -92
  64. package/src/manifests/textarea.json +0 -117
  65. package/src/manifests/toast.json +0 -157
  66. package/src/manifests/tooltip.json +0 -115
  67. package/src/server.ts +0 -201
  68. package/src/tools/build-index.ts +0 -55
  69. package/src/tools/check-a11y.ts +0 -106
  70. package/src/tools/embedder.ts +0 -18
  71. package/src/tools/generate-theme.ts +0 -42
  72. package/src/tools/get-emmet.ts +0 -64
  73. package/src/tools/get-manifests.ts +0 -55
  74. package/src/tools/intent-engine.ts +0 -197
  75. package/src/tools/list-components.ts +0 -20
  76. package/src/tools/search-index.ts +0 -66
  77. package/src/tools/theme-palette.ts +0 -65
  78. package/src/tools/theme-tokens.ts +0 -176
  79. package/src/tools/validator.ts +0 -367
  80. package/src/types.ts +0 -63
  81. package/src/utils/a11y-rules.ts +0 -873
  82. package/src/utils/a11y-types.ts +0 -15
  83. package/src/utils/check-api.ts +0 -13
  84. package/src/utils/cosine.ts +0 -15
  85. package/src/utils/emmet-helpers.ts +0 -171
  86. package/src/utils/intent-helpers.ts +0 -66
  87. package/src/utils/intent-parser.ts +0 -186
  88. package/src/utils/tokenizer.ts +0 -7
  89. package/tsconfig.json +0 -14
  90. package/tsup.config.ts +0 -13
@@ -1,367 +0,0 @@
1
- import { parse } from 'node-html-parser'
2
- import { manifests } from '../manifests/index.js'
3
- import type { MCPResponse } from '../types.js'
4
-
5
- type ErrorType =
6
- | 'UNKNOWN_ATTRIBUTE'
7
- | 'INVALID_VALUE'
8
- | 'FORBIDDEN_CLASS'
9
- | 'MISSING_REQUIRED'
10
- | 'WRONG_ELEMENT'
11
- | 'PROP_EXPLOSION'
12
- | 'JS_ON_CSS_COMPONENT'
13
- | 'MISSING_SLOT'
14
-
15
- type ValidationError = {
16
- element: string
17
- prop: string
18
- type: ErrorType
19
- message: string
20
- suggestion?: string
21
- valid_values?: string[]
22
- fix: string
23
- confidence: number
24
- }
25
-
26
- export function validate(html: string): MCPResponse {
27
- const root = parse(html)
28
-
29
- const errors: ValidationError[] = []
30
-
31
- const elements = root.querySelectorAll('*')
32
-
33
- // SRS wrappers only
34
- const allowedWrappers = [
35
- 'label',
36
- 'span',
37
- 'p',
38
- 'img',
39
- 'small',
40
- 'h1',
41
- 'h2',
42
- 'h3',
43
- 'a',
44
- 'button',
45
- 'ul',
46
- 'li',
47
- 'thead',
48
- 'tbody',
49
- 'tr',
50
- 'td',
51
- 'th',
52
- 'summary'
53
- ]
54
-
55
- const nativeAttributes = new Set([
56
- 'id',
57
- 'role',
58
- 'slot',
59
- 'tabindex',
60
-
61
- 'aria-label',
62
- 'aria-live',
63
- 'aria-hidden',
64
- 'aria-expanded',
65
- 'aria-selected',
66
- 'aria-current',
67
- 'aria-sort',
68
- 'aria-invalid',
69
- 'aria-describedby',
70
- 'aria-labelledby',
71
- 'aria-haspopup',
72
- 'aria-busy',
73
-
74
- 'disabled',
75
- 'required',
76
- 'checked',
77
- 'multiple',
78
- 'readonly',
79
-
80
- 'type',
81
- 'value',
82
- 'placeholder',
83
- 'name',
84
-
85
- 'min',
86
- 'max',
87
- 'low',
88
- 'high',
89
- 'optimum',
90
-
91
- 'rows',
92
-
93
- 'open',
94
- 'hidden',
95
-
96
- 'href',
97
-
98
- 'content',
99
-
100
- 'is',
101
-
102
- 'src',
103
- 'alt',
104
-
105
- 'data-intent',
106
- 'data-position',
107
- 'data-variant',
108
- 'data-shape',
109
- 'data-sortable',
110
- 'data-open',
111
- 'data-lines',
112
-
113
- 'data-grid',
114
- 'data-gap',
115
- 'data-align',
116
- 'data-justify',
117
- 'data-col',
118
- 'data-row',
119
- 'data-dense'
120
- ])
121
-
122
- for (const el of elements) {
123
- const tag = el.tagName.toLowerCase()
124
-
125
- const attrs = el.attributes
126
-
127
- // ix-* support
128
- let manifestKey = tag.startsWith('ix-') ? tag.slice(3) : tag
129
-
130
- // built in table
131
- if (tag === 'table' && attrs.is === 'ix-table') {
132
- manifestKey = 'table'
133
- }
134
-
135
- // navigation
136
- if (tag === 'nav') {
137
- manifestKey = 'navigation'
138
- }
139
-
140
- // card
141
- if (tag === 'article' && el.querySelector('[slot]')) {
142
- manifestKey = 'card'
143
- }
144
-
145
- let manifest = manifests[manifestKey]
146
-
147
- // badge support
148
- if (!manifest) {
149
- if (tag === 'mark') {
150
- manifest = manifests.badge
151
- }
152
-
153
- if (tag === 'span' && attrs.role === 'status') {
154
- manifest = manifests.badge
155
- }
156
- }
157
-
158
- // invalid component
159
- if (!manifest && !allowedWrappers.includes(tag)) {
160
- errors.push({
161
- element: tag,
162
- prop: '',
163
- type: 'WRONG_ELEMENT',
164
- message: `<${tag}> is not a valid ignix-lite component`,
165
- fix: `<button>Fix me</button>`,
166
- confidence: 0.7
167
- })
168
-
169
- continue
170
- }
171
-
172
- // wrappers skip
173
- if (!manifest) continue
174
-
175
- const elementName = tag.startsWith('ix-') ? tag : manifest.element || tag
176
-
177
- // required wrapper
178
- if (manifest.required_wrapper) {
179
- const parent = el.parentNode as unknown as {
180
- tagName?: string
181
- }
182
-
183
- if (
184
- !parent ||
185
- parent.tagName?.toLowerCase() !== manifest.required_wrapper
186
- ) {
187
- errors.push({
188
- element: tag,
189
- prop: 'wrapper',
190
- type: 'MISSING_REQUIRED',
191
- message: `<${tag}> must be inside <${manifest.required_wrapper}>`,
192
- fix: `<${manifest.required_wrapper}><${elementName}></${elementName}></${manifest.required_wrapper}>`,
193
- confidence: 0.95
194
- })
195
- }
196
- }
197
-
198
- // badge rule
199
- if (
200
- tag === 'span' &&
201
- manifest.component === 'badge' &&
202
- attrs.role !== 'status'
203
- ) {
204
- errors.push({
205
- element: tag,
206
-
207
- prop: 'role',
208
- type: 'INVALID_VALUE',
209
- message: 'span badge must have role=status',
210
- fix: `<span role="status">${el.innerText}</span>`,
211
- confidence: 0.9
212
- })
213
- }
214
-
215
- // class forbidden
216
- if ('class' in attrs) {
217
- errors.push({
218
- element: tag,
219
- prop: 'class',
220
- type: 'FORBIDDEN_CLASS',
221
- message: 'class attribute not allowed',
222
- fix: `<${elementName}>${el.innerText}</${elementName}>`,
223
- confidence: 0.99
224
- })
225
- }
226
-
227
- // prop explosion
228
- if (Object.keys(attrs).length > 4) {
229
- errors.push({
230
- element: tag,
231
- prop: 'multiple',
232
- type: 'PROP_EXPLOSION',
233
- message: 'Too many props',
234
- fix: `<${elementName}></${elementName}>`,
235
- confidence: 0.85
236
- })
237
- }
238
-
239
- // js handlers
240
- for (const attr of Object.keys(attrs)) {
241
- if (attr.startsWith('on')) {
242
- errors.push({
243
- element: tag,
244
- prop: attr,
245
- type: 'JS_ON_CSS_COMPONENT',
246
- message: 'JS handlers forbidden',
247
- fix: `<${elementName}></${elementName}>`,
248
- confidence: 0.95
249
- })
250
- }
251
- }
252
-
253
- // attribute validation
254
- for (const attr of Object.keys(attrs)) {
255
- if (manifest.forbidden_props?.includes(attr)) {
256
- errors.push({
257
- element: tag,
258
- prop: attr,
259
- type: 'UNKNOWN_ATTRIBUTE',
260
- message: `'${attr}' forbidden`,
261
- fix: `<${elementName}></${elementName}>`,
262
- confidence: 0.98
263
- })
264
-
265
- continue
266
- }
267
-
268
- if (!manifest.props?.[attr] && !nativeAttributes.has(attr)) {
269
- errors.push({
270
- element: tag,
271
- prop: attr,
272
- type: 'UNKNOWN_ATTRIBUTE',
273
- message: `'${attr}' invalid`,
274
- fix: `<${elementName}></${elementName}>`,
275
- confidence: 0.95
276
- })
277
- }
278
- }
279
-
280
- // enum validation
281
- for (const attr of Object.keys(attrs)) {
282
- const def = manifest.props?.[attr]
283
-
284
- if (def?.values) {
285
- const value = attrs[attr]
286
-
287
- if (!def.values.includes(value)) {
288
- errors.push({
289
- element: tag,
290
- prop: attr,
291
- type: 'INVALID_VALUE',
292
- message: `'${value}' invalid`,
293
- valid_values: def.values,
294
- fix: `<${elementName} ${attr}="${def.values[0]}"></${elementName}>`,
295
- confidence: 0.97
296
- })
297
- }
298
- }
299
- }
300
-
301
- // required props
302
- for (const req of manifest.required_props || []) {
303
- if (!(req in attrs)) {
304
- errors.push({
305
- element: tag,
306
- prop: req,
307
- type: 'MISSING_REQUIRED',
308
- message: `Missing ${req}`,
309
- fix: `<${elementName} ${req}=""></${elementName}>`,
310
- confidence: 0.9
311
- })
312
- }
313
- }
314
-
315
- // slot validation
316
- const slots = manifest.slots ?? {}
317
-
318
- for (const [slotName, slotDef] of Object.entries(slots)) {
319
- const child = el.querySelector(`[slot="${slotName}"]`)
320
-
321
- if (slotDef.required && !child) {
322
- errors.push({
323
- element: tag,
324
- prop: slotName,
325
- type: 'MISSING_SLOT',
326
- message: `Missing slot ${slotName}`,
327
- fix: `<${elementName}><span slot="${slotName}"></span></${elementName}>`,
328
- confidence: 0.95
329
- })
330
- }
331
-
332
- if (child && slotDef.element) {
333
- const childTag = child.tagName.toLowerCase()
334
-
335
- if (!slotDef.element.includes(childTag)) {
336
- errors.push({
337
- element: childTag,
338
- prop: slotName,
339
- type: 'INVALID_VALUE',
340
- message: `${childTag} invalid for slot ${slotName}`,
341
- valid_values: slotDef.element,
342
- fix: `<${slotDef.element[0]} slot="${slotName}"></${slotDef.element[0]}>`,
343
- confidence: 0.95
344
- })
345
- }
346
- }
347
- }
348
- }
349
-
350
- const valid = errors.length === 0
351
- const score = valid ? 100 : Math.max(0, 100 - errors.length * 10)
352
-
353
- return {
354
- content: [
355
- {
356
- type: 'text',
357
-
358
- text: JSON.stringify({
359
- valid,
360
- score,
361
- errors,
362
- tokens_used: 50
363
- })
364
- }
365
- ]
366
- }
367
- }
package/src/types.ts DELETED
@@ -1,63 +0,0 @@
1
- export type ToolName =
2
- | 'list_components'
3
- | 'get_manifest'
4
- | 'get_emmet'
5
- | 'validate'
6
-
7
- export type ToolRequest = {
8
- params: {
9
- name: ToolName
10
-
11
- arguments?: unknown
12
- }
13
- }
14
-
15
- export type MCPResponse = {
16
- content: {
17
- type: 'text'
18
- text: string
19
-
20
- }[]
21
- }
22
-
23
- export type ManifestProp = {
24
- type: string
25
- values?: string[]
26
- default?: string | boolean
27
- native?: boolean
28
- agent_hint?: string
29
- }
30
-
31
- export type ManifestSlot = {
32
- required: boolean
33
- element: string[]
34
- agent_hint?: string
35
- }
36
-
37
- export type ManifestExample = {
38
- label: string
39
- emmet: string
40
- html: string
41
- }
42
-
43
- export type Manifest = {
44
- component: string
45
- version: string
46
- description: string
47
- element: string
48
- emmet: string
49
- tokens: number
50
- props: Record<string, ManifestProp>
51
- slots?: Record<string, ManifestSlot>
52
- states?: string[]
53
- forbidden_props?: string[]
54
- required_props?: string[]
55
- required_slots?: string[]
56
- required_wrapper?: string
57
- methods?: string[]
58
- do?: string[]
59
- dont?: string[]
60
- examples?: ManifestExample[]
61
- extends?: string
62
-
63
- }