canicode 0.8.8 → 0.9.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/.claude/skills/design-to-code/PROMPT.md +143 -0
- package/README.md +94 -63
- package/dist/cli/index.js +8332 -4577
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +621 -233
- package/dist/index.js +2963 -2047
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.js +3469 -2833
- package/dist/mcp/server.js.map +1 -1
- package/docs/CUSTOMIZATION.md +208 -0
- package/package.json +14 -4
- package/docs/REFERENCE.md +0 -479
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# Customization Guide
|
|
2
|
+
|
|
3
|
+
CanICode supports two types of customization:
|
|
4
|
+
|
|
5
|
+
1. **Config overrides** — adjust scores, severity, and node exclusions
|
|
6
|
+
2. **Custom rules** — add project-specific checks
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Config Overrides
|
|
11
|
+
|
|
12
|
+
Override built-in rule scores, severity, and filter settings with a JSON file.
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
canicode analyze <url> --config ./my-config.json
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### Full Schema
|
|
19
|
+
|
|
20
|
+
```json
|
|
21
|
+
{
|
|
22
|
+
"excludeNodeTypes": ["VECTOR", "BOOLEAN_OPERATION", "SLICE"],
|
|
23
|
+
"excludeNodeNames": ["chatbot", "ad-banner", "custom-widget"],
|
|
24
|
+
"gridBase": 2,
|
|
25
|
+
"rules": {
|
|
26
|
+
"no-auto-layout": { "score": -15, "severity": "blocking", "enabled": true },
|
|
27
|
+
"raw-value": { "score": -5 },
|
|
28
|
+
"non-semantic-name": { "enabled": false }
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Fields
|
|
34
|
+
|
|
35
|
+
| Field | Type | Default | Description |
|
|
36
|
+
|-------|------|---------|-------------|
|
|
37
|
+
| `excludeNodeTypes` | `string[]` | `[]` | Figma node types to skip entirely (node + children) |
|
|
38
|
+
| `excludeNodeNames` | `string[]` | `[]` | Name patterns to skip (case-insensitive word match) |
|
|
39
|
+
| `gridBase` | `number` | `2` | Spacing grid unit for `irregular-spacing` |
|
|
40
|
+
| `rules` | `object` | — | Per-rule overrides (see below) |
|
|
41
|
+
|
|
42
|
+
### Node Exclusions
|
|
43
|
+
|
|
44
|
+
**`excludeNodeNames`** — Nodes whose name contains any of these words (case-insensitive) will be skipped entirely. The node and all its children are excluded from analysis.
|
|
45
|
+
|
|
46
|
+
```json
|
|
47
|
+
{
|
|
48
|
+
"excludeNodeNames": ["chatbot", "floating-cta", "ad-banner", "legacy"]
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
This matches word boundaries, so `"nav"` matches `"Nav Bar"` and `"bottom-nav"` but not `"unavailable"`.
|
|
53
|
+
|
|
54
|
+
**Built-in exclusions** (always active for conversion candidates):
|
|
55
|
+
`badge`, `close`, `dismiss`, `overlay`, `float`, `fab`, `dot`, `indicator`, `corner`, `decoration`, `tag`, `status`, `notification`, `icon`, `ico`, `image`, `asset`, `filter`, `dim`, `dimmed`, `bg`, `background`, `logo`, `avatar`, `divider`, `separator`, `nav`, `navigation`, `gnb`, `header`, `footer`, `sidebar`, `toolbar`, `modal`, `dialog`, `popup`, `toast`, `tooltip`, `dropdown`, `menu`, `sticky`, `spinner`, `loader`, `cursor`, `cta`, `chatbot`, `thumb`, `thumbnail`, `tabbar`, `tab-bar`, `statusbar`, `status-bar`
|
|
56
|
+
|
|
57
|
+
**`excludeNodeTypes`** — Figma node types to skip.
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
{
|
|
61
|
+
"excludeNodeTypes": ["VECTOR", "BOOLEAN_OPERATION", "SLICE", "STICKY"]
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Available types: `DOCUMENT`, `CANVAS`, `FRAME`, `GROUP`, `SECTION`, `COMPONENT`, `COMPONENT_SET`, `INSTANCE`, `RECTANGLE`, `ELLIPSE`, `VECTOR`, `TEXT`, `LINE`, `BOOLEAN_OPERATION`, `STAR`, `REGULAR_POLYGON`, `SLICE`, `STICKY`, `TABLE`, `TABLE_CELL`
|
|
66
|
+
|
|
67
|
+
### Per-Rule Overrides
|
|
68
|
+
|
|
69
|
+
Override score, severity, or enable/disable individual rules:
|
|
70
|
+
|
|
71
|
+
```json
|
|
72
|
+
{
|
|
73
|
+
"rules": {
|
|
74
|
+
"no-auto-layout": {
|
|
75
|
+
"score": -15,
|
|
76
|
+
"severity": "blocking"
|
|
77
|
+
},
|
|
78
|
+
"non-semantic-name": {
|
|
79
|
+
"enabled": false
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
| Property | Type | Description |
|
|
86
|
+
|----------|------|-------------|
|
|
87
|
+
| `score` | `number` (≤ 0) | Penalty score (more negative = harsher) |
|
|
88
|
+
| `severity` | `string` | `"blocking"`, `"risk"`, `"missing-info"`, or `"suggestion"` |
|
|
89
|
+
| `enabled` | `boolean` | Set `false` to disable the rule |
|
|
90
|
+
|
|
91
|
+
### All Rule IDs
|
|
92
|
+
|
|
93
|
+
<!-- RULE_TABLE_START — auto-generated by scripts/sync-rule-docs.ts, do not edit manually -->
|
|
94
|
+
**Pixel Critical (3 rules)**
|
|
95
|
+
|
|
96
|
+
| Rule ID | Default Score | Default Severity |
|
|
97
|
+
|---------|--------------|-----------------|
|
|
98
|
+
| `no-auto-layout` | -10 | blocking |
|
|
99
|
+
| `absolute-position-in-auto-layout` | -7 | blocking |
|
|
100
|
+
| `non-layout-container` | -8 | blocking |
|
|
101
|
+
|
|
102
|
+
**Responsive Critical (2 rules)**
|
|
103
|
+
|
|
104
|
+
| Rule ID | Default Score | Default Severity |
|
|
105
|
+
|---------|--------------|-----------------|
|
|
106
|
+
| `fixed-size-in-auto-layout` | -6 | risk |
|
|
107
|
+
| `missing-size-constraint` | -8 | risk |
|
|
108
|
+
|
|
109
|
+
**Code Quality (4 rules)**
|
|
110
|
+
|
|
111
|
+
| Rule ID | Default Score | Default Severity |
|
|
112
|
+
|---------|--------------|-----------------|
|
|
113
|
+
| `deep-nesting` | -3 | risk |
|
|
114
|
+
| `missing-component` | -7 | risk |
|
|
115
|
+
| `detached-instance` | -4 | risk |
|
|
116
|
+
| `variant-structure-mismatch` | -6 | risk |
|
|
117
|
+
|
|
118
|
+
**Token Management (2 rules)**
|
|
119
|
+
|
|
120
|
+
| Rule ID | Default Score | Default Severity |
|
|
121
|
+
|---------|--------------|-----------------|
|
|
122
|
+
| `raw-value` | -4 | missing-info |
|
|
123
|
+
| `irregular-spacing` | -5 | risk |
|
|
124
|
+
|
|
125
|
+
**Semantic (3 rules)**
|
|
126
|
+
|
|
127
|
+
| Rule ID | Default Score | Default Severity |
|
|
128
|
+
|---------|--------------|-----------------|
|
|
129
|
+
| `non-semantic-name` | -4 | risk |
|
|
130
|
+
| `inconsistent-naming-convention` | -1 | suggestion |
|
|
131
|
+
| `non-standard-naming` | -3 | suggestion |
|
|
132
|
+
|
|
133
|
+
**Interaction (2 rules)**
|
|
134
|
+
|
|
135
|
+
| Rule ID | Default Score | Default Severity |
|
|
136
|
+
|---------|--------------|-----------------|
|
|
137
|
+
| `missing-interaction-state` | -1 | suggestion |
|
|
138
|
+
| `missing-prototype` *(disabled)* | -3 | missing-info |
|
|
139
|
+
<!-- RULE_TABLE_END -->
|
|
140
|
+
|
|
141
|
+
### Example Configs
|
|
142
|
+
|
|
143
|
+
**Strict (for production-ready designs):**
|
|
144
|
+
```json
|
|
145
|
+
{
|
|
146
|
+
"rules": {
|
|
147
|
+
"no-auto-layout": { "score": -15 },
|
|
148
|
+
"raw-value": { "score": -5, "severity": "risk" },
|
|
149
|
+
"non-semantic-name": { "score": -6, "severity": "blocking" }
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
**Relaxed (for early prototypes):**
|
|
155
|
+
```json
|
|
156
|
+
{
|
|
157
|
+
"excludeNodeNames": ["prototype", "wip", "draft", "temp"],
|
|
158
|
+
"rules": {
|
|
159
|
+
"non-semantic-name": { "enabled": false },
|
|
160
|
+
"missing-component": { "severity": "suggestion" }
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
**Mobile-first (focus on structure):**
|
|
166
|
+
|
|
167
|
+
```json
|
|
168
|
+
{
|
|
169
|
+
"rules": {
|
|
170
|
+
"fixed-size-in-auto-layout": { "score": -8, "severity": "blocking" },
|
|
171
|
+
"no-auto-layout": { "score": -12 }
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
## Telemetry
|
|
181
|
+
|
|
182
|
+
CanICode collects anonymous usage analytics via [PostHog](https://posthog.com) and error tracking via [Sentry](https://sentry.io). This helps improve the tool by understanding which features are used and catching errors early.
|
|
183
|
+
|
|
184
|
+
### What is tracked
|
|
185
|
+
|
|
186
|
+
- Event names with `cic_` prefix (e.g. `cic_analysis_completed`, `cic_cli_command`)
|
|
187
|
+
- Aggregate metadata: node count, issue count, grade, duration
|
|
188
|
+
- Error messages (stack traces for debugging)
|
|
189
|
+
|
|
190
|
+
### What is NOT tracked
|
|
191
|
+
|
|
192
|
+
- No design data, file contents, or Figma tokens
|
|
193
|
+
- No personally identifiable information
|
|
194
|
+
- No file names or URLs
|
|
195
|
+
|
|
196
|
+
### How to opt out
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
canicode config --no-telemetry # disable telemetry
|
|
200
|
+
canicode config --telemetry # re-enable telemetry
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
Telemetry is enabled by default. When disabled, all monitoring functions become silent no-ops.
|
|
204
|
+
|
|
205
|
+
### Implementation
|
|
206
|
+
|
|
207
|
+
Telemetry uses native `fetch` (Node 18+ / browser) — no external dependencies. API keys are injected at build time. When telemetry is disabled, all capture functions become silent no-ops.
|
|
208
|
+
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "canicode",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"mcpName": "io.github.let-sunny/canicode",
|
|
5
|
-
"description": "
|
|
5
|
+
"description": "Score your Figma designs with AI-calibrated rules. CLI + MCP server.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./dist/index.js",
|
|
8
8
|
"types": "./dist/index.d.ts",
|
|
@@ -24,11 +24,13 @@
|
|
|
24
24
|
"test:run": "vitest run",
|
|
25
25
|
"lint": "tsc --noEmit",
|
|
26
26
|
"build:plugin": "bash scripts/build-plugin.sh",
|
|
27
|
+
"sync-docs": "tsx scripts/sync-rule-docs.ts",
|
|
27
28
|
"clean": "rm -rf dist"
|
|
28
29
|
},
|
|
29
30
|
"files": [
|
|
30
31
|
"dist",
|
|
31
|
-
"docs/
|
|
32
|
+
"docs/CUSTOMIZATION.md",
|
|
33
|
+
".claude/skills/design-to-code/PROMPT.md"
|
|
32
34
|
],
|
|
33
35
|
"keywords": [
|
|
34
36
|
"figma",
|
|
@@ -49,9 +51,15 @@
|
|
|
49
51
|
"homepage": "https://github.com/let-sunny/canicode",
|
|
50
52
|
"author": "minseon",
|
|
51
53
|
"license": "MIT",
|
|
54
|
+
"pnpm": {
|
|
55
|
+
"overrides": {
|
|
56
|
+
"picomatch": "4.0.4",
|
|
57
|
+
"path-to-regexp": "8.4.0"
|
|
58
|
+
}
|
|
59
|
+
},
|
|
52
60
|
"packageManager": "pnpm@10.32.1",
|
|
53
61
|
"engines": {
|
|
54
|
-
"node": ">=
|
|
62
|
+
"node": ">=22"
|
|
55
63
|
},
|
|
56
64
|
"dependencies": {
|
|
57
65
|
"@figma/rest-api-spec": "^0.36.0",
|
|
@@ -63,11 +71,13 @@
|
|
|
63
71
|
"zod": "^4.3.6"
|
|
64
72
|
},
|
|
65
73
|
"devDependencies": {
|
|
74
|
+
"@anthropic-ai/sdk": "^0.80.0",
|
|
66
75
|
"@figma/plugin-typings": "^1.123.0",
|
|
67
76
|
"@types/node": "^25.5.0",
|
|
68
77
|
"@types/pngjs": "^6.0.5",
|
|
69
78
|
"playwright": "^1.58.2",
|
|
70
79
|
"tsup": "^8.5.1",
|
|
80
|
+
"tsx": "^4.19.0",
|
|
71
81
|
"typescript": "^5.9.3",
|
|
72
82
|
"vitest": "^4.1.0"
|
|
73
83
|
}
|