@urbicon-ui/mcp-server 6.1.4
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 +161 -0
- package/dist/data/catalog-loader.d.ts +37 -0
- package/dist/data/catalog-loader.d.ts.map +1 -0
- package/dist/data/catalog-loader.js +15 -0
- package/dist/data/catalog-loader.js.map +1 -0
- package/dist/data/component-loader.d.ts +2 -0
- package/dist/data/component-loader.d.ts.map +1 -0
- package/dist/data/component-loader.js +17 -0
- package/dist/data/component-loader.js.map +1 -0
- package/dist/data/recipe-loader.d.ts +4 -0
- package/dist/data/recipe-loader.d.ts.map +1 -0
- package/dist/data/recipe-loader.js +102 -0
- package/dist/data/recipe-loader.js.map +1 -0
- package/dist/data/template-loader.d.ts +8 -0
- package/dist/data/template-loader.d.ts.map +1 -0
- package/dist/data/template-loader.js +33 -0
- package/dist/data/template-loader.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +57 -0
- package/dist/index.js.map +1 -0
- package/dist/resources/catalog.d.ts +3 -0
- package/dist/resources/catalog.d.ts.map +1 -0
- package/dist/resources/catalog.js +20 -0
- package/dist/resources/catalog.js.map +1 -0
- package/dist/resources/component.d.ts +3 -0
- package/dist/resources/component.d.ts.map +1 -0
- package/dist/resources/component.js +29 -0
- package/dist/resources/component.js.map +1 -0
- package/dist/resources/guides.d.ts +3 -0
- package/dist/resources/guides.d.ts.map +1 -0
- package/dist/resources/guides.js +36 -0
- package/dist/resources/guides.js.map +1 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/find-components.d.ts +3 -0
- package/dist/tools/find-components.d.ts.map +1 -0
- package/dist/tools/find-components.js +21 -0
- package/dist/tools/find-components.js.map +1 -0
- package/dist/tools/get-recipe.d.ts +3 -0
- package/dist/tools/get-recipe.d.ts.map +1 -0
- package/dist/tools/get-recipe.js +48 -0
- package/dist/tools/get-recipe.js.map +1 -0
- package/dist/tools/suggest-implementation.d.ts +3 -0
- package/dist/tools/suggest-implementation.d.ts.map +1 -0
- package/dist/tools/suggest-implementation.js +178 -0
- package/dist/tools/suggest-implementation.js.map +1 -0
- package/dist/transports/http.d.ts +2 -0
- package/dist/transports/http.d.ts.map +1 -0
- package/dist/transports/http.js +77 -0
- package/dist/transports/http.js.map +1 -0
- package/dist/transports/stdio.d.ts +3 -0
- package/dist/transports/stdio.d.ts.map +1 -0
- package/dist/transports/stdio.js +6 -0
- package/dist/transports/stdio.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/utils/format-catalog.d.ts +7 -0
- package/dist/utils/format-catalog.d.ts.map +1 -0
- package/dist/utils/format-catalog.js +93 -0
- package/dist/utils/format-catalog.js.map +1 -0
- package/dist/utils/paths.d.ts +7 -0
- package/dist/utils/paths.d.ts.map +1 -0
- package/dist/utils/paths.js +23 -0
- package/dist/utils/paths.js.map +1 -0
- package/dist/utils/search.d.ts +3 -0
- package/dist/utils/search.d.ts.map +1 -0
- package/dist/utils/search.js +44 -0
- package/dist/utils/search.js.map +1 -0
- package/package.json +42 -0
- package/src/data/catalog-loader.test.ts +42 -0
- package/src/data/catalog-loader.ts +78 -0
- package/src/data/component-loader.ts +68 -0
- package/src/data/design-system-loader.test.ts +82 -0
- package/src/data/design-system-loader.ts +125 -0
- package/src/data/icon-loader.test.ts +85 -0
- package/src/data/icon-loader.ts +90 -0
- package/src/data/recipe-loader.test.ts +49 -0
- package/src/data/recipe-loader.ts +131 -0
- package/src/data/template-loader.ts +55 -0
- package/src/design-linter/heuristics.ts +162 -0
- package/src/design-linter/index.ts +14 -0
- package/src/design-linter/linter.test.ts +257 -0
- package/src/design-linter/linter.ts +62 -0
- package/src/design-linter/rules.ts +348 -0
- package/src/design-linter/tokens.test.ts +80 -0
- package/src/design-linter/tokens.ts +203 -0
- package/src/design-linter/types.ts +66 -0
- package/src/design-manifest/index.ts +20 -0
- package/src/design-manifest/manifest.test.ts +175 -0
- package/src/design-manifest/manifest.ts +250 -0
- package/src/design-manifest/scan.test.ts +51 -0
- package/src/design-manifest/scan.ts +74 -0
- package/src/design-manifest/types.ts +40 -0
- package/src/design-rubric/rubric.test.ts +43 -0
- package/src/design-rubric/rubric.ts +140 -0
- package/src/eval/briefs.ts +104 -0
- package/src/eval/eval.test.ts +99 -0
- package/src/eval/index.ts +11 -0
- package/src/eval/score.ts +112 -0
- package/src/index.ts +75 -0
- package/src/prompts/design-prompts.test.ts +51 -0
- package/src/prompts/design-prompts.ts +127 -0
- package/src/resources/catalog.ts +23 -0
- package/src/resources/guides.ts +60 -0
- package/src/server.test.ts +69 -0
- package/src/server.ts +48 -0
- package/src/tools/find-components.ts +83 -0
- package/src/tools/find-icons.ts +77 -0
- package/src/tools/get-checklist.ts +139 -0
- package/src/tools/get-component.ts +204 -0
- package/src/tools/get-css-reference.ts +446 -0
- package/src/tools/get-design-context.ts +43 -0
- package/src/tools/get-design-principles.ts +72 -0
- package/src/tools/get-pattern.ts +69 -0
- package/src/tools/get-recipe.ts +80 -0
- package/src/tools/record-design-decision.ts +99 -0
- package/src/tools/suggest-implementation.ts +251 -0
- package/src/tools/sync-design-manifest.ts +92 -0
- package/src/tools/validate-design.ts +84 -0
- package/src/transports/http.ts +79 -0
- package/src/transports/stdio.ts +7 -0
- package/src/utils/format-catalog.test.ts +144 -0
- package/src/utils/format-catalog.ts +130 -0
- package/src/utils/paths.test.ts +101 -0
- package/src/utils/paths.ts +78 -0
- package/src/utils/search.test.ts +141 -0
- package/src/utils/search.ts +106 -0
- package/tsconfig.json +27 -0
- package/vitest.config.ts +15 -0
package/README.md
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# @urbicon-ui/mcp-server
|
|
2
|
+
|
|
3
|
+
Model Context Protocol server for the Urbicon UI design system. Gives LLMs first-class access to the component catalog, design tokens, recipes, and implementation guidance — the AI-native DX pillar of Urbicon.
|
|
4
|
+
|
|
5
|
+
**Transports:** stdio (default, for IDE integrations like Claude Code / Cursor) and streamable HTTP (for remote editors).
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
This package ships inside the Urbicon UI monorepo. Install from repo root:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
bun install
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Runtime dependencies: `@modelcontextprotocol/sdk`, `zod`.
|
|
16
|
+
|
|
17
|
+
> **Bun is required.** `package.json#main` points at `./src/index.ts`
|
|
18
|
+
> directly — there is no transpilation step. The server is intended to
|
|
19
|
+
> be launched via `bun run` (see Quick Start). Tools like `npm i -g` or
|
|
20
|
+
> Node-only setups will not work; use Bun or wire the entry through a
|
|
21
|
+
> Bun wrapper script.
|
|
22
|
+
|
|
23
|
+
## Quick Start
|
|
24
|
+
|
|
25
|
+
### Stdio (IDE integration)
|
|
26
|
+
|
|
27
|
+
From the repo root:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
bun run mcp:start
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Or directly:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
bun run packages/mcp-server/src/index.ts
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### HTTP (remote)
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
bun run mcp:start:http
|
|
43
|
+
# listens on http://localhost:3001 with streamable transport
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Connect from Claude Code
|
|
47
|
+
|
|
48
|
+
Add to `~/.claude/mcp.json` (or project `.claude/mcp.json`):
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"mcpServers": {
|
|
53
|
+
"urbicon-ui": {
|
|
54
|
+
"command": "bun",
|
|
55
|
+
"args": ["run", "/absolute/path/to/urbicon-ui/packages/mcp-server/src/index.ts"]
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
For Cursor: see [Cursor's MCP docs](https://docs.cursor.com/context/model-context-protocol).
|
|
62
|
+
|
|
63
|
+
## Tools
|
|
64
|
+
|
|
65
|
+
Most tools are read-only (`readOnlyHint: true`). The two manifest-writing tools (`record_design_decision`, `sync_design_manifest`) write `design.manifest.md` in the project root. Queries are Zod-validated.
|
|
66
|
+
|
|
67
|
+
| Tool | Purpose |
|
|
68
|
+
| ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
69
|
+
| `find_components` | Fuzzy search across component names, tags, and descriptions. Filterable by package (`blocks`, `table`, `auth`). |
|
|
70
|
+
| `get_component` | Full per-component documentation: props, variants, slots, examples, source link. Optional `section` argument for streamed chunks (overview / examples / variants / api / slots). |
|
|
71
|
+
| `get_recipe` | Full production-ready recipe (login-form, dashboard, settings-page, etc.) with component tree, code, and notes. |
|
|
72
|
+
| `suggest_implementation` | Takes a natural-language goal and returns a component-tree suggestion, relevant recipes, Style-Patterns guide, and the implementation checklist. |
|
|
73
|
+
| `get_implementation_checklist` | Design-Quality checklist (visual weight, intent semantics, spacing, radius, data-driven styling, dominance, identity) — embedded directly so the LLM can self-verify. |
|
|
74
|
+
| `get_css_reference` | Full token reference — surface, text, border, intent, feedback tokens, radii, z-index. Includes an explicit "do not invent tokens" guardrail. |
|
|
75
|
+
| `find_icons` | Browse the 156-icon catalog by keyword, category, or name. |
|
|
76
|
+
| `get_design_principles` | Design heuristics (Layer 5): visual hierarchy, interaction, component selection, layout, accessibility, theming (paradigms, change decision tree). Call first when generating UI. `as="rubric"` returns the 8-criterion 1–5 scoring rubric for judging a generated UI. |
|
|
77
|
+
| `get_pattern` | Composition patterns (Layer 4) for page archetypes — settings-page, dashboard, form-page, tab-navigation, onboarding-guide. |
|
|
78
|
+
| `validate_design` | Lint generated markup against the design rules — raw colours, `dark:`/`focus:` misuse, hardcoded z-index, broken dynamic classes, hallucinated tokens, plus distribution heuristics. Returns a 0–100 score and per-finding fixes for a generate → validate → fix loop. |
|
|
79
|
+
| `get_design_context` | Read the project's `design.manifest.md`: chosen paradigm/theme/density, which pages use which composition patterns, and recorded design decisions (ADRs). Call at the start of a UI task to stay consistent with prior decisions. |
|
|
80
|
+
| `record_design_decision` | Append a design decision (ADR) to the manifest — record a deliberate deviation from a pattern or principle so future sessions honour it. Writes `design.manifest.md`. |
|
|
81
|
+
| `sync_design_manifest` | Scan the project source for `data-design-pattern` markers and regenerate the manifest's Pattern Usages index — makes a pattern change tractable (grep the markers → migrate every listed file). |
|
|
82
|
+
|
|
83
|
+
## Resources
|
|
84
|
+
|
|
85
|
+
| URI | Purpose |
|
|
86
|
+
| -------------------------------- | -------------------------------------------------------------------------------------------------- |
|
|
87
|
+
| `urbicon://catalog` | Full component catalog in Markdown — used as the LLM's default context |
|
|
88
|
+
| `urbicon://guide/api-grammar` | Canonical prop conventions (`intent`, `variant`, `size`, callbacks) |
|
|
89
|
+
| `urbicon://guide/design-quality` | AVOID/INSTEAD patterns from A/B-tested design-quality guidance (+33.8 % improvement in user study) |
|
|
90
|
+
| `urbicon://guide/style-patterns` | Reusable style presets and composition templates |
|
|
91
|
+
| `urbicon://guide/tokens` | OKLCH token reference, same data as `get_css_reference` |
|
|
92
|
+
|
|
93
|
+
## Prompts
|
|
94
|
+
|
|
95
|
+
Client-agnostic workflows (Option E of the design loop) — invoke them from any MCP client to run the full generate → validate → judge → synthesise process rather than a single-shot generation.
|
|
96
|
+
|
|
97
|
+
| Prompt | Arguments | Purpose |
|
|
98
|
+
| ------------- | -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
99
|
+
| `design-page` | `brief`, `pattern?`, `variants?` | Design a new page: load context + pattern, explore N variants within the paradigm, gate each on `validate_design`, score with the rubric, synthesise the winner. |
|
|
100
|
+
| `redesign` | `brief`, `code?`, `variants?` | Redesign an existing page: diagnose with `validate_design` + the rubric, then fix exactly the flagged weaknesses while preserving behaviour. |
|
|
101
|
+
|
|
102
|
+
## CLI Options
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
urbicon-mcp [--transport <stdio|http>] [--port <n>] [--data-dir <path>]
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
| Flag | Default | Purpose |
|
|
109
|
+
| ------------- | ------------- | ------------------------------------------------------------ |
|
|
110
|
+
| `--transport` | `stdio` | Transport mode |
|
|
111
|
+
| `--port` | `3001` | HTTP port (ignored for stdio) |
|
|
112
|
+
| `--data-dir` | auto-discover | Override the path to the generated catalog/templates/recipes |
|
|
113
|
+
|
|
114
|
+
## Architecture
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
src/
|
|
118
|
+
├── index.ts CLI entry + arg parsing, pre-loads catalog/templates/recipes
|
|
119
|
+
├── server.ts MCP server construction (registers resources + tools)
|
|
120
|
+
├── transports/
|
|
121
|
+
│ ├── stdio.ts Stdio transport
|
|
122
|
+
│ └── http.ts Streamable HTTP transport (per-session)
|
|
123
|
+
├── tools/ 13 tools, each self-contained
|
|
124
|
+
├── design-linter/ validate_design engine: rules, token whitelist, heuristics (pure, unit-tested)
|
|
125
|
+
├── design-manifest/ design.manifest.md parse/scan/edit for the design-context tools
|
|
126
|
+
├── resources/ Catalog + guide resources
|
|
127
|
+
├── data/ Loaders with in-process caching
|
|
128
|
+
│ ├── catalog-loader.ts component-catalog.json
|
|
129
|
+
│ ├── template-loader.ts llms.txt sections
|
|
130
|
+
│ ├── recipe-loader.ts Recipes
|
|
131
|
+
│ ├── design-system-loader.ts principles.md + patterns/*.md
|
|
132
|
+
│ ├── component-loader.ts
|
|
133
|
+
│ └── icon-loader.ts
|
|
134
|
+
└── utils/ search, format-catalog, paths
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
The server reads its data from artifacts produced by [`@urbicon-ui/docs-gen`](../docs-gen/) (`component-catalog.json`, per-component `llms.txt`, recipes). That means JSDoc in a component's `index.ts` is the **single source of truth**: one edit propagates to the docs site, `llms-full.txt`, and every MCP tool.
|
|
138
|
+
|
|
139
|
+
## Development
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
bun --filter='@urbicon-ui/mcp-server' run dev # watch mode (stdio)
|
|
143
|
+
bun --filter='@urbicon-ui/mcp-server' run start # stdio, one-shot
|
|
144
|
+
bun --filter='@urbicon-ui/mcp-server' run start:http # HTTP on port 3001
|
|
145
|
+
bun --filter='@urbicon-ui/mcp-server' run check # tsc --noEmit
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Bun runs TypeScript directly — no build step.
|
|
149
|
+
|
|
150
|
+
## Roadmap
|
|
151
|
+
|
|
152
|
+
Next steps:
|
|
153
|
+
|
|
154
|
+
- **`compose_layout`** — takes natural-language intent and returns a full component tree with props (v1.x)
|
|
155
|
+
- **`llm.json` per component** — structured, token-efficient sibling of `llm.txt` (v1.x)
|
|
156
|
+
|
|
157
|
+
Smoke tests for catalog loading, tool wiring, and fuzzy search are already in place (`bunx --bun vitest run` in this package).
|
|
158
|
+
|
|
159
|
+
## Related
|
|
160
|
+
|
|
161
|
+
- [`@urbicon-ui/docs-gen`](../docs-gen/) — produces the catalog and llms.txt files this server reads
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export interface ComponentCatalogEntry {
|
|
2
|
+
name: string;
|
|
3
|
+
slug: string;
|
|
4
|
+
package: string;
|
|
5
|
+
group: 'primitives' | 'components' | 'core';
|
|
6
|
+
description: string;
|
|
7
|
+
tags: string[];
|
|
8
|
+
import: string;
|
|
9
|
+
llmTxtPath: string;
|
|
10
|
+
variants: {
|
|
11
|
+
name: string;
|
|
12
|
+
values: string[];
|
|
13
|
+
default?: string;
|
|
14
|
+
}[];
|
|
15
|
+
keyProps: string[];
|
|
16
|
+
slots: string[];
|
|
17
|
+
hasExamples: boolean;
|
|
18
|
+
relatedComponents: string[];
|
|
19
|
+
}
|
|
20
|
+
export interface RecipeEntry {
|
|
21
|
+
id: string;
|
|
22
|
+
title: string;
|
|
23
|
+
description: string;
|
|
24
|
+
components: string[];
|
|
25
|
+
code: string;
|
|
26
|
+
features: string[];
|
|
27
|
+
}
|
|
28
|
+
export interface ComponentCatalog {
|
|
29
|
+
generated: string;
|
|
30
|
+
version: string;
|
|
31
|
+
components: ComponentCatalogEntry[];
|
|
32
|
+
recipes: RecipeEntry[];
|
|
33
|
+
tags: string[];
|
|
34
|
+
}
|
|
35
|
+
export declare function loadCatalog(): Promise<ComponentCatalog>;
|
|
36
|
+
export declare function getCachedCatalog(): ComponentCatalog | null;
|
|
37
|
+
//# sourceMappingURL=catalog-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog-loader.d.ts","sourceRoot":"","sources":["../../src/data/catalog-loader.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,YAAY,GAAG,YAAY,GAAG,MAAM,CAAC;IAC5C,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACjE,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;IACrB,iBAAiB,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,qBAAqB,EAAE,CAAC;IACpC,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAID,wBAAsB,WAAW,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAO7D;AAED,wBAAgB,gBAAgB,IAAI,gBAAgB,GAAG,IAAI,CAE1D"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { getCatalogPath } from '../utils/paths.js';
|
|
3
|
+
let cachedCatalog = null;
|
|
4
|
+
export async function loadCatalog() {
|
|
5
|
+
if (cachedCatalog)
|
|
6
|
+
return cachedCatalog;
|
|
7
|
+
const catalogPath = getCatalogPath();
|
|
8
|
+
const raw = await readFile(catalogPath, 'utf-8');
|
|
9
|
+
cachedCatalog = JSON.parse(raw);
|
|
10
|
+
return cachedCatalog;
|
|
11
|
+
}
|
|
12
|
+
export function getCachedCatalog() {
|
|
13
|
+
return cachedCatalog;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=catalog-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog-loader.js","sourceRoot":"","sources":["../../src/data/catalog-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAmCnD,IAAI,aAAa,GAA4B,IAAI,CAAC;AAElD,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,IAAI,aAAa;QAAE,OAAO,aAAa,CAAC;IAExC,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IACjD,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAqB,CAAC;IACpD,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,OAAO,aAAa,CAAC;AACvB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"component-loader.d.ts","sourceRoot":"","sources":["../../src/data/component-loader.ts"],"names":[],"mappings":"AAKA,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAW9E"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { readFile, access } from 'node:fs/promises';
|
|
2
|
+
import { getComponentLlmPath } from '../utils/paths.js';
|
|
3
|
+
const SEARCH_GROUPS = ['blocks/primitives', 'blocks/components', 'docs/components', 'table'];
|
|
4
|
+
export async function loadComponentLlmTxt(slug) {
|
|
5
|
+
for (const group of SEARCH_GROUPS) {
|
|
6
|
+
const path = getComponentLlmPath(group, slug);
|
|
7
|
+
try {
|
|
8
|
+
await access(path);
|
|
9
|
+
return await readFile(path, 'utf-8');
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
continue;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=component-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"component-loader.js","sourceRoot":"","sources":["../../src/data/component-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAExD,MAAM,aAAa,GAAG,CAAC,mBAAmB,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,OAAO,CAAC,CAAC;AAE7F,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,IAAY;IACpD,KAAK,MAAM,KAAK,IAAI,aAAa,EAAE,CAAC;QAClC,MAAM,IAAI,GAAG,mBAAmB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QAC9C,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;YACnB,OAAO,MAAM,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACvC,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recipe-loader.d.ts","sourceRoot":"","sources":["../../src/data/recipe-loader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAqEvD,wBAAsB,WAAW,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAuC1D;AAED,wBAAsB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAG3E"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { readFile, readdir, stat } from 'node:fs/promises';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
import { getRecipeDir } from '../utils/paths.js';
|
|
4
|
+
let cachedRecipes = null;
|
|
5
|
+
function extractArray(content, varName) {
|
|
6
|
+
const pattern = new RegExp(`const\\s+${varName}\\s*=\\s*\\[([^\\]]+)\\]`, 's');
|
|
7
|
+
const match = content.match(pattern);
|
|
8
|
+
if (!match?.[1])
|
|
9
|
+
return [];
|
|
10
|
+
return match[1]
|
|
11
|
+
.split(',')
|
|
12
|
+
.map((s) => s.trim().replace(/^['"]|['"]$/g, ''))
|
|
13
|
+
.filter((s) => s.length > 0 && !s.includes('{'));
|
|
14
|
+
}
|
|
15
|
+
function extractRecipeCode(content) {
|
|
16
|
+
// Find the recipeCode assignment start
|
|
17
|
+
const startMatch = content.match(/const\s+recipeCode\s*=\s*\n?\s*/);
|
|
18
|
+
if (!startMatch)
|
|
19
|
+
return '';
|
|
20
|
+
const startIdx = (startMatch.index ?? 0) + startMatch[0].length;
|
|
21
|
+
const rest = content.slice(startIdx);
|
|
22
|
+
// Find the end: a backtick followed by a semicolon (possibly with whitespace)
|
|
23
|
+
// We need to track backtick nesting to handle `...` + `...`;
|
|
24
|
+
let depth = 0;
|
|
25
|
+
let endIdx = -1;
|
|
26
|
+
for (let i = 0; i < rest.length; i++) {
|
|
27
|
+
if (rest[i] === '`') {
|
|
28
|
+
depth = depth === 0 ? 1 : 0;
|
|
29
|
+
}
|
|
30
|
+
if (depth === 0 && rest[i] === ';') {
|
|
31
|
+
endIdx = i;
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (endIdx === -1)
|
|
36
|
+
return '';
|
|
37
|
+
const raw = rest.slice(0, endIdx);
|
|
38
|
+
// Split on backtick concatenation (`...` + `...`) and rejoin
|
|
39
|
+
// This handles the </scr` + `ipt> pattern used to avoid parser issues
|
|
40
|
+
const parts = raw.split(/`\s*\+\s*\n?\s*`/);
|
|
41
|
+
return parts.map((p) => p.replace(/^\s*`|`\s*$/g, '')).join('');
|
|
42
|
+
}
|
|
43
|
+
function extractTitle(content, dirName) {
|
|
44
|
+
const titleMatch = content.match(/<title>([^<]+)<\/title>/);
|
|
45
|
+
if (titleMatch?.[1]) {
|
|
46
|
+
return titleMatch[1].replace(/\s*[-|].*$/, '').trim();
|
|
47
|
+
}
|
|
48
|
+
return dirName
|
|
49
|
+
.split('-')
|
|
50
|
+
.map((w) => w.charAt(0).toUpperCase() + w.slice(1))
|
|
51
|
+
.join(' ');
|
|
52
|
+
}
|
|
53
|
+
function extractDescription(content) {
|
|
54
|
+
const descMatch = content.match(/<p\s+class="text-text-secondary[^"]*"[^>]*>\s*([\s\S]*?)\s*<\/p>/);
|
|
55
|
+
if (descMatch?.[1]) {
|
|
56
|
+
return descMatch[1].replace(/<[^>]+>/g, '').trim();
|
|
57
|
+
}
|
|
58
|
+
return '';
|
|
59
|
+
}
|
|
60
|
+
export async function loadRecipes() {
|
|
61
|
+
if (cachedRecipes)
|
|
62
|
+
return cachedRecipes;
|
|
63
|
+
const recipeDir = getRecipeDir();
|
|
64
|
+
const entries = [];
|
|
65
|
+
let dirs;
|
|
66
|
+
try {
|
|
67
|
+
dirs = await readdir(recipeDir);
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
cachedRecipes = [];
|
|
71
|
+
return [];
|
|
72
|
+
}
|
|
73
|
+
for (const dirName of dirs) {
|
|
74
|
+
const dirPath = resolve(recipeDir, dirName);
|
|
75
|
+
const dirStat = await stat(dirPath).catch(() => null);
|
|
76
|
+
if (!dirStat?.isDirectory())
|
|
77
|
+
continue;
|
|
78
|
+
const pagePath = resolve(dirPath, '+page.svelte');
|
|
79
|
+
let content;
|
|
80
|
+
try {
|
|
81
|
+
content = await readFile(pagePath, 'utf-8');
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
entries.push({
|
|
87
|
+
id: dirName,
|
|
88
|
+
title: extractTitle(content, dirName),
|
|
89
|
+
description: extractDescription(content),
|
|
90
|
+
components: extractArray(content, 'usedComponents'),
|
|
91
|
+
code: extractRecipeCode(content),
|
|
92
|
+
features: extractArray(content, 'features')
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
cachedRecipes = entries;
|
|
96
|
+
return entries;
|
|
97
|
+
}
|
|
98
|
+
export async function getRecipeById(id) {
|
|
99
|
+
const recipes = await loadRecipes();
|
|
100
|
+
return recipes.find((r) => r.id === id) ?? null;
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=recipe-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recipe-loader.js","sourceRoot":"","sources":["../../src/data/recipe-loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface TemplateSections {
|
|
2
|
+
'api-grammar': string;
|
|
3
|
+
tokens: string;
|
|
4
|
+
customization: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function loadTemplateSections(): Promise<TemplateSections>;
|
|
7
|
+
export declare function getCachedSections(): TemplateSections | null;
|
|
8
|
+
//# sourceMappingURL=template-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-loader.d.ts","sourceRoot":"","sources":["../../src/data/template-loader.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,gBAAgB;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;CACvB;AAmBD,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,gBAAgB,CAAC,CActE;AAED,wBAAgB,iBAAiB,IAAI,gBAAgB,GAAG,IAAI,CAE3D"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { getTemplatePath } from '../utils/paths.js';
|
|
3
|
+
let cachedSections = null;
|
|
4
|
+
function extractSection(lines, startHeading, endMarker) {
|
|
5
|
+
const startIdx = lines.findIndex((l) => l.trim().startsWith(startHeading));
|
|
6
|
+
if (startIdx === -1)
|
|
7
|
+
return '';
|
|
8
|
+
let endIdx = lines.length;
|
|
9
|
+
for (let i = startIdx + 1; i < lines.length; i++) {
|
|
10
|
+
if (lines[i]?.trim() === endMarker) {
|
|
11
|
+
endIdx = i;
|
|
12
|
+
break;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return lines.slice(startIdx, endIdx).join('\n').trim();
|
|
16
|
+
}
|
|
17
|
+
export async function loadTemplateSections() {
|
|
18
|
+
if (cachedSections)
|
|
19
|
+
return cachedSections;
|
|
20
|
+
const templatePath = getTemplatePath();
|
|
21
|
+
const raw = await readFile(templatePath, 'utf-8');
|
|
22
|
+
const lines = raw.split('\n');
|
|
23
|
+
cachedSections = {
|
|
24
|
+
'api-grammar': extractSection(lines, '## Shared API Grammar', '---'),
|
|
25
|
+
tokens: extractSection(lines, '## Design Token System', '---'),
|
|
26
|
+
customization: extractSection(lines, '## Customization', '---')
|
|
27
|
+
};
|
|
28
|
+
return cachedSections;
|
|
29
|
+
}
|
|
30
|
+
export function getCachedSections() {
|
|
31
|
+
return cachedSections;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=template-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-loader.js","sourceRoot":"","sources":["../../src/data/template-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAQpD,IAAI,cAAc,GAA4B,IAAI,CAAC;AAEnD,SAAS,cAAc,CAAC,KAAe,EAAE,YAAoB,EAAE,SAAiB;IAC9E,MAAM,QAAQ,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC;IAC3E,IAAI,QAAQ,KAAK,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAE/B,IAAI,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IAC1B,KAAK,IAAI,CAAC,GAAG,QAAQ,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACjD,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;YACnC,MAAM,GAAG,CAAC,CAAC;YACX,MAAM;QACR,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;AACzD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB;IACxC,IAAI,cAAc;QAAE,OAAO,cAAc,CAAC;IAE1C,MAAM,YAAY,GAAG,eAAe,EAAE,CAAC;IACvC,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IAClD,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAE9B,cAAc,GAAG;QACf,aAAa,EAAE,cAAc,CAAC,KAAK,EAAE,uBAAuB,EAAE,KAAK,CAAC;QACpE,MAAM,EAAE,cAAc,CAAC,KAAK,EAAE,wBAAwB,EAAE,KAAK,CAAC;QAC9D,aAAa,EAAE,cAAc,CAAC,KAAK,EAAE,kBAAkB,EAAE,KAAK,CAAC;KAChE,CAAC;IAEF,OAAO,cAAc,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,OAAO,cAAc,CAAC;AACxB,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createServer } from './server.js';
|
|
3
|
+
import { startStdioTransport } from './transports/stdio.js';
|
|
4
|
+
import { startHttpTransport } from './transports/http.js';
|
|
5
|
+
import { loadCatalog } from './data/catalog-loader.js';
|
|
6
|
+
import { loadTemplateSections } from './data/template-loader.js';
|
|
7
|
+
import { loadRecipes } from './data/recipe-loader.js';
|
|
8
|
+
function parseArgs(args) {
|
|
9
|
+
const result = {
|
|
10
|
+
transport: 'stdio',
|
|
11
|
+
port: 3001
|
|
12
|
+
};
|
|
13
|
+
for (let i = 0; i < args.length; i++) {
|
|
14
|
+
const arg = args[i];
|
|
15
|
+
const next = args[i + 1];
|
|
16
|
+
if (arg === '--transport' && next) {
|
|
17
|
+
if (next === 'stdio' || next === 'http') {
|
|
18
|
+
result.transport = next;
|
|
19
|
+
}
|
|
20
|
+
i++;
|
|
21
|
+
}
|
|
22
|
+
else if (arg === '--port' && next) {
|
|
23
|
+
result.port = parseInt(next, 10);
|
|
24
|
+
i++;
|
|
25
|
+
}
|
|
26
|
+
else if (arg === '--data-dir' && next) {
|
|
27
|
+
result.dataDir = next;
|
|
28
|
+
i++;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return result;
|
|
32
|
+
}
|
|
33
|
+
async function main() {
|
|
34
|
+
const args = parseArgs(process.argv.slice(2));
|
|
35
|
+
if (args.dataDir) {
|
|
36
|
+
process.env.DATA_DIR = args.dataDir;
|
|
37
|
+
}
|
|
38
|
+
// Pre-load cached data
|
|
39
|
+
try {
|
|
40
|
+
await Promise.all([loadCatalog(), loadTemplateSections(), loadRecipes()]);
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
console.error('Warning: Failed to pre-load some data:', err);
|
|
44
|
+
}
|
|
45
|
+
if (args.transport === 'http') {
|
|
46
|
+
await startHttpTransport(args.port);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
const server = createServer();
|
|
50
|
+
await startStdioTransport(server);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
main().catch((err) => {
|
|
54
|
+
console.error('Fatal error:', err);
|
|
55
|
+
process.exit(1);
|
|
56
|
+
});
|
|
57
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAQtD,SAAS,SAAS,CAAC,IAAc;IAC/B,MAAM,MAAM,GAAY;QACtB,SAAS,EAAE,OAAO;QAClB,IAAI,EAAE,IAAI;KACX,CAAC;IAEF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAEzB,IAAI,GAAG,KAAK,aAAa,IAAI,IAAI,EAAE,CAAC;YAClC,IAAI,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;gBACxC,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC;YAC1B,CAAC;YACD,CAAC,EAAE,CAAC;QACN,CAAC;aAAM,IAAI,GAAG,KAAK,QAAQ,IAAI,IAAI,EAAE,CAAC;YACpC,MAAM,CAAC,IAAI,GAAG,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YACjC,CAAC,EAAE,CAAC;QACN,CAAC;aAAM,IAAI,GAAG,KAAK,YAAY,IAAI,IAAI,EAAE,CAAC;YACxC,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;YACtB,CAAC,EAAE,CAAC;QACN,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAE9C,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,OAAO,CAAC,GAAG,CAAC,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC;IACtC,CAAC;IAED,uBAAuB;IACvB,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE,oBAAoB,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC;IAC5E,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,wCAAwC,EAAE,GAAG,CAAC,CAAC;IAC/D,CAAC;IAED,IAAI,IAAI,CAAC,SAAS,KAAK,MAAM,EAAE,CAAC;QAC9B,MAAM,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC;SAAM,CAAC;QACN,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;QAC9B,MAAM,mBAAmB,CAAC,MAAM,CAAC,CAAC;IACpC,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC;IACnC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/resources/catalog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIzE,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAkB/D"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { loadCatalog } from '../data/catalog-loader.js';
|
|
2
|
+
import { formatCompactCatalog } from '../utils/format-catalog.js';
|
|
3
|
+
export function registerCatalogResource(server) {
|
|
4
|
+
server.resource('catalog', 'urbicon://catalog', async (uri) => {
|
|
5
|
+
const catalog = await loadCatalog();
|
|
6
|
+
const md = formatCompactCatalog(catalog.components, {
|
|
7
|
+
recipes: catalog.recipes
|
|
8
|
+
});
|
|
9
|
+
return {
|
|
10
|
+
contents: [
|
|
11
|
+
{
|
|
12
|
+
uri: uri.href,
|
|
13
|
+
mimeType: 'text/markdown',
|
|
14
|
+
text: md
|
|
15
|
+
}
|
|
16
|
+
]
|
|
17
|
+
};
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=catalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../src/resources/catalog.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAElE,MAAM,UAAU,uBAAuB,CAAC,MAAiB;IACvD,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,mBAAmB,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QAC5D,MAAM,OAAO,GAAG,MAAM,WAAW,EAAE,CAAC;QAEpC,MAAM,EAAE,GAAG,oBAAoB,CAAC,OAAO,CAAC,UAAU,EAAE;YAClD,OAAO,EAAE,OAAO,CAAC,OAAO;SACzB,CAAC,CAAC;QAEH,OAAO;YACL,QAAQ,EAAE;gBACR;oBACE,GAAG,EAAE,GAAG,CAAC,IAAI;oBACb,QAAQ,EAAE,eAAe;oBACzB,IAAI,EAAE,EAAE;iBACT;aACF;SACF,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../../src/resources/component.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGzE,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA4BjE"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { loadComponentLlmTxt } from '../data/component-loader.js';
|
|
2
|
+
export function registerComponentResource(server) {
|
|
3
|
+
server.resource('component', 'urbicon://component/{name}', async (uri, _extra) => {
|
|
4
|
+
// Extract component name from URI path: urbicon://component/{name}
|
|
5
|
+
const name = uri.pathname.split('/').pop() || '';
|
|
6
|
+
const content = await loadComponentLlmTxt(name);
|
|
7
|
+
if (!content) {
|
|
8
|
+
return {
|
|
9
|
+
contents: [
|
|
10
|
+
{
|
|
11
|
+
uri: uri.href,
|
|
12
|
+
mimeType: 'text/plain',
|
|
13
|
+
text: `Component "${name}" not found. Use the catalog resource to see available components.`
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
return {
|
|
19
|
+
contents: [
|
|
20
|
+
{
|
|
21
|
+
uri: uri.href,
|
|
22
|
+
mimeType: 'text/markdown',
|
|
23
|
+
text: content
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
};
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"component.js","sourceRoot":"","sources":["../../src/resources/component.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAElE,MAAM,UAAU,yBAAyB,CAAC,MAAiB;IACzD,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAE,4BAA4B,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE;QAC/E,mEAAmE;QACnE,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;QACjD,MAAM,OAAO,GAAG,MAAM,mBAAmB,CAAC,IAAI,CAAC,CAAC;QAEhD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO;gBACL,QAAQ,EAAE;oBACR;wBACE,GAAG,EAAE,GAAG,CAAC,IAAI;wBACb,QAAQ,EAAE,YAAY;wBACtB,IAAI,EAAE,cAAc,IAAI,oEAAoE;qBAC7F;iBACF;aACF,CAAC;QACJ,CAAC;QAED,OAAO;YACL,QAAQ,EAAE;gBACR;oBACE,GAAG,EAAE,GAAG,CAAC,IAAI;oBACb,QAAQ,EAAE,eAAe;oBACzB,IAAI,EAAE,OAAO;iBACd;aACF;SACF,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guides.d.ts","sourceRoot":"","sources":["../../src/resources/guides.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAsBzE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAiB9D"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { loadTemplateSections } from '../data/template-loader.js';
|
|
2
|
+
const GUIDE_RESOURCES = [
|
|
3
|
+
{
|
|
4
|
+
id: 'api-grammar',
|
|
5
|
+
name: 'API Grammar Guide',
|
|
6
|
+
key: 'api-grammar'
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
id: 'tokens',
|
|
10
|
+
name: 'Design Tokens Guide',
|
|
11
|
+
key: 'tokens'
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
id: 'customization',
|
|
15
|
+
name: 'Customization Guide',
|
|
16
|
+
key: 'customization'
|
|
17
|
+
}
|
|
18
|
+
];
|
|
19
|
+
export function registerGuideResources(server) {
|
|
20
|
+
for (const guide of GUIDE_RESOURCES) {
|
|
21
|
+
server.resource(`guide-${guide.id}`, `urbicon://guide/${guide.id}`, async (uri) => {
|
|
22
|
+
const sections = await loadTemplateSections();
|
|
23
|
+
const content = sections[guide.key];
|
|
24
|
+
return {
|
|
25
|
+
contents: [
|
|
26
|
+
{
|
|
27
|
+
uri: uri.href,
|
|
28
|
+
mimeType: 'text/markdown',
|
|
29
|
+
text: content || `Guide section "${guide.id}" not found.`
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
};
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=guides.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guides.js","sourceRoot":"","sources":["../../src/resources/guides.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAGlE,MAAM,eAAe,GAAgE;IACnF;QACE,EAAE,EAAE,aAAa;QACjB,IAAI,EAAE,mBAAmB;QACzB,GAAG,EAAE,aAAa;KACnB;IACD;QACE,EAAE,EAAE,QAAQ;QACZ,IAAI,EAAE,qBAAqB;QAC3B,GAAG,EAAE,QAAQ;KACd;IACD;QACE,EAAE,EAAE,eAAe;QACnB,IAAI,EAAE,qBAAqB;QAC3B,GAAG,EAAE,eAAe;KACrB;CACF,CAAC;AAEF,MAAM,UAAU,sBAAsB,CAAC,MAAiB;IACtD,KAAK,MAAM,KAAK,IAAI,eAAe,EAAE,CAAC;QACpC,MAAM,CAAC,QAAQ,CAAC,SAAS,KAAK,CAAC,EAAE,EAAE,EAAE,mBAAmB,KAAK,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;YAChF,MAAM,QAAQ,GAAG,MAAM,oBAAoB,EAAE,CAAC;YAC9C,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAEpC,OAAO;gBACL,QAAQ,EAAE;oBACR;wBACE,GAAG,EAAE,GAAG,CAAC,IAAI;wBACb,QAAQ,EAAE,eAAe;wBACzB,IAAI,EAAE,OAAO,IAAI,kBAAkB,KAAK,CAAC,EAAE,cAAc;qBAC1D;iBACF;aACF,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
|
package/dist/server.d.ts
ADDED