canicode 0.3.0 → 0.3.2

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.
@@ -0,0 +1,273 @@
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": 4,
25
+ "colorTolerance": 5,
26
+ "rules": {
27
+ "no-auto-layout": { "score": -15, "severity": "blocking", "enabled": true },
28
+ "raw-color": { "score": -12 },
29
+ "default-name": { "enabled": false }
30
+ }
31
+ }
32
+ ```
33
+
34
+ ### Fields
35
+
36
+ | Field | Type | Default | Description |
37
+ |-------|------|---------|-------------|
38
+ | `excludeNodeTypes` | `string[]` | `[]` | Figma node types to skip entirely (node + children) |
39
+ | `excludeNodeNames` | `string[]` | `[]` | Name patterns to skip (case-insensitive word match) |
40
+ | `gridBase` | `number` | `8` | Spacing grid unit for `inconsistent-spacing` and `magic-number-spacing` |
41
+ | `colorTolerance` | `number` | `10` | Color difference tolerance for `multiple-fill-colors` |
42
+ | `rules` | `object` | — | Per-rule overrides (see below) |
43
+
44
+ ### Node Exclusions
45
+
46
+ **`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.
47
+
48
+ ```json
49
+ {
50
+ "excludeNodeNames": ["chatbot", "floating-cta", "ad-banner", "legacy"]
51
+ }
52
+ ```
53
+
54
+ This matches word boundaries, so `"nav"` matches `"Nav Bar"` and `"bottom-nav"` but not `"unavailable"`.
55
+
56
+ **Built-in exclusions** (always active for conversion candidates):
57
+ `icon`, `ico`, `badge`, `indicator`, `image`, `asset`, `chatbot`, `cta`, `gnb`, `navigation`, `nav`, `fab`, `modal`, `dialog`, `popup`, `overlay`, `toast`, `snackbar`, `tooltip`, `dropdown`, `menu`, `sticky`, `bg`, `background`, `divider`, `separator`, `logo`, `avatar`, `thumbnail`, `thumb`, `header`, `footer`, `sidebar`, `toolbar`, `tabbar`, `tab-bar`, `statusbar`, `status-bar`, `spinner`, `loader`, `cursor`, `dot`, `dim`, `dimmed`, `filter`
58
+
59
+ **`excludeNodeTypes`** — Figma node types to skip.
60
+
61
+ ```json
62
+ {
63
+ "excludeNodeTypes": ["VECTOR", "BOOLEAN_OPERATION", "SLICE", "STICKY"]
64
+ }
65
+ ```
66
+
67
+ 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`
68
+
69
+ ### Per-Rule Overrides
70
+
71
+ Override score, severity, or enable/disable individual rules:
72
+
73
+ ```json
74
+ {
75
+ "rules": {
76
+ "no-auto-layout": {
77
+ "score": -15,
78
+ "severity": "blocking"
79
+ },
80
+ "default-name": {
81
+ "enabled": false
82
+ }
83
+ }
84
+ }
85
+ ```
86
+
87
+ | Property | Type | Description |
88
+ |----------|------|-------------|
89
+ | `score` | `number` (≤ 0) | Penalty score (more negative = harsher) |
90
+ | `severity` | `string` | `"blocking"`, `"risk"`, `"missing-info"`, or `"suggestion"` |
91
+ | `enabled` | `boolean` | Set `false` to disable the rule |
92
+
93
+ ### All Rule IDs
94
+
95
+ **Layout (11 rules)**
96
+
97
+ | Rule ID | Default Score | Default Severity |
98
+ |---------|--------------|-----------------|
99
+ | `no-auto-layout` | -7 | blocking |
100
+ | `absolute-position-in-auto-layout` | -10 | blocking |
101
+ | `fixed-width-in-responsive-context` | -4 | risk |
102
+ | `missing-responsive-behavior` | -4 | risk |
103
+ | `group-usage` | -5 | risk |
104
+ | `fixed-size-in-auto-layout` | -5 | risk |
105
+ | `missing-min-width` | -5 | risk |
106
+ | `missing-max-width` | -4 | risk |
107
+ | `deep-nesting` | -4 | risk |
108
+ | `overflow-hidden-abuse` | -3 | missing-info |
109
+ | `inconsistent-sibling-layout-direction` | -2 | missing-info |
110
+
111
+ **Token (7 rules)**
112
+
113
+ | Rule ID | Default Score | Default Severity |
114
+ |---------|--------------|-----------------|
115
+ | `raw-color` | -2 | missing-info |
116
+ | `raw-font` | -8 | blocking |
117
+ | `inconsistent-spacing` | -2 | missing-info |
118
+ | `magic-number-spacing` | -3 | missing-info |
119
+ | `raw-shadow` | -7 | risk |
120
+ | `raw-opacity` | -5 | risk |
121
+ | `multiple-fill-colors` | -3 | missing-info |
122
+
123
+ **Component (6 rules)**
124
+
125
+ | Rule ID | Default Score | Default Severity |
126
+ |---------|--------------|-----------------|
127
+ | `missing-component` | -7 | risk |
128
+ | `detached-instance` | -5 | risk |
129
+ | `nested-instance-override` | -3 | missing-info |
130
+ | `variant-not-used` | -3 | suggestion |
131
+ | `component-property-unused` | -2 | suggestion |
132
+ | `single-use-component` | -2 | suggestion |
133
+
134
+ **Naming (5 rules)**
135
+
136
+ | Rule ID | Default Score | Default Severity |
137
+ |---------|--------------|-----------------|
138
+ | `default-name` | -2 | missing-info |
139
+ | `non-semantic-name` | -2 | missing-info |
140
+ | `inconsistent-naming-convention` | -2 | missing-info |
141
+ | `numeric-suffix-name` | -2 | missing-info |
142
+ | `too-long-name` | -1 | suggestion |
143
+
144
+ **AI Readability (5 rules)**
145
+
146
+ | Rule ID | Default Score | Default Severity |
147
+ |---------|--------------|-----------------|
148
+ | `ambiguous-structure` | -10 | blocking |
149
+ | `z-index-dependent-layout` | -5 | risk |
150
+ | `missing-layout-hint` | -3 | missing-info |
151
+ | `invisible-layer` | -10 | blocking |
152
+ | `empty-frame` | -2 | missing-info |
153
+
154
+ **Handoff Risk (5 rules)**
155
+
156
+ | Rule ID | Default Score | Default Severity |
157
+ |---------|--------------|-----------------|
158
+ | `hardcode-risk` | -5 | risk |
159
+ | `text-truncation-unhandled` | -5 | risk |
160
+ | `image-no-placeholder` | -4 | risk |
161
+ | `prototype-link-in-design` | -2 | suggestion |
162
+ | `no-dev-status` | -2 | suggestion |
163
+
164
+ ### Example Configs
165
+
166
+ **Strict (for production-ready designs):**
167
+ ```json
168
+ {
169
+ "rules": {
170
+ "no-auto-layout": { "score": -15 },
171
+ "raw-color": { "score": -10, "severity": "blocking" },
172
+ "default-name": { "score": -8, "severity": "blocking" }
173
+ }
174
+ }
175
+ ```
176
+
177
+ **Relaxed (for early prototypes):**
178
+ ```json
179
+ {
180
+ "excludeNodeNames": ["prototype", "wip", "draft", "temp"],
181
+ "rules": {
182
+ "default-name": { "enabled": false },
183
+ "non-semantic-name": { "enabled": false },
184
+ "missing-component": { "severity": "suggestion" }
185
+ }
186
+ }
187
+ ```
188
+
189
+ **Mobile-first (focus on layout):**
190
+ ```json
191
+ {
192
+ "rules": {
193
+ "missing-responsive-behavior": { "score": -10, "severity": "blocking" },
194
+ "fixed-width-in-responsive-context": { "score": -8, "severity": "blocking" },
195
+ "no-auto-layout": { "score": -12 }
196
+ }
197
+ }
198
+ ```
199
+
200
+ ---
201
+
202
+ ## Custom Rules
203
+
204
+ Add project-specific checks that don't exist in the built-in 39 rules.
205
+
206
+ ```bash
207
+ canicode analyze <url> --custom-rules ./my-rules.json
208
+ ```
209
+
210
+ ### Schema
211
+
212
+ ```json
213
+ [
214
+ {
215
+ "id": "my-rule-id",
216
+ "category": "component",
217
+ "severity": "blocking",
218
+ "score": -10,
219
+ "prompt": "Describe what to check on this Figma node...",
220
+ "why": "Why this matters for developers.",
221
+ "impact": "What happens if this issue is not fixed.",
222
+ "fix": "How to fix it in Figma."
223
+ }
224
+ ]
225
+ ```
226
+
227
+ | Field | Required | Description |
228
+ |-------|----------|-------------|
229
+ | `id` | Yes | Unique rule identifier (kebab-case) |
230
+ | `category` | Yes | `layout`, `token`, `component`, `naming`, `ai-readability`, or `handoff-risk` |
231
+ | `severity` | Yes | `blocking`, `risk`, `missing-info`, or `suggestion` |
232
+ | `score` | Yes | Penalty score (negative integer) |
233
+ | `prompt` | Yes | What to check — describes the condition for this rule |
234
+ | `why` | Yes | Why this rule matters (shown in reports) |
235
+ | `impact` | Yes | Developer impact if not fixed (shown in reports) |
236
+ | `fix` | Yes | How to fix it in Figma (shown in reports) |
237
+
238
+ ### Example Custom Rules
239
+
240
+ ```json
241
+ [
242
+ {
243
+ "id": "icon-missing-component",
244
+ "category": "component",
245
+ "severity": "blocking",
246
+ "score": -10,
247
+ "prompt": "Check if this node is an icon (small size, vector children, no text) and is not a component or instance.",
248
+ "why": "Icon nodes that are not components cannot be reused consistently.",
249
+ "impact": "Developers will hardcode icons instead of using a shared component.",
250
+ "fix": "Convert to a component and publish to the library."
251
+ },
252
+ {
253
+ "id": "missing-dark-mode-token",
254
+ "category": "token",
255
+ "severity": "risk",
256
+ "score": -7,
257
+ "prompt": "Check if this node uses color fills that are not bound to a Figma variable.",
258
+ "why": "Hardcoded colors cannot be swapped for dark mode variants.",
259
+ "impact": "Dark mode requires manual overrides for every affected node.",
260
+ "fix": "Replace hardcoded colors with Figma variables that support mode switching."
261
+ }
262
+ ]
263
+ ```
264
+
265
+ ### Combining Config + Custom Rules
266
+
267
+ Both flags work together:
268
+
269
+ ```bash
270
+ canicode analyze <url> --config ./config.json --custom-rules ./rules.json
271
+ ```
272
+
273
+ The config adjusts built-in rules, while custom rules add new checks on top.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "canicode",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "CLI tool that analyzes Figma design structures for development-friendliness and AI-friendliness scores",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -25,7 +25,8 @@
25
25
  "clean": "rm -rf dist"
26
26
  },
27
27
  "files": [
28
- "dist"
28
+ "dist",
29
+ "docs/CUSTOMIZATION.md"
29
30
  ],
30
31
  "keywords": [
31
32
  "figma",