canicode 0.8.4 → 0.8.5
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 +84 -22
- package/dist/cli/index.js +213 -4
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +27 -5
- package/dist/index.js +61 -4
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.js +57 -2
- package/dist/mcp/server.js.map +1 -1
- package/package.json +4 -1
package/dist/mcp/server.js
CHANGED
|
@@ -178,7 +178,7 @@ var RULE_CONFIGS = {
|
|
|
178
178
|
}
|
|
179
179
|
},
|
|
180
180
|
// ============================================
|
|
181
|
-
// Component (
|
|
181
|
+
// Component (7 rules)
|
|
182
182
|
// ============================================
|
|
183
183
|
"missing-component": {
|
|
184
184
|
severity: "risk",
|
|
@@ -213,6 +213,11 @@ var RULE_CONFIGS = {
|
|
|
213
213
|
score: -1,
|
|
214
214
|
enabled: true
|
|
215
215
|
},
|
|
216
|
+
"missing-component-description": {
|
|
217
|
+
severity: "missing-info",
|
|
218
|
+
score: -2,
|
|
219
|
+
enabled: true
|
|
220
|
+
},
|
|
216
221
|
// ============================================
|
|
217
222
|
// Naming (5 rules)
|
|
218
223
|
// ============================================
|
|
@@ -795,6 +800,20 @@ function transformNode(node) {
|
|
|
795
800
|
}
|
|
796
801
|
return base;
|
|
797
802
|
}
|
|
803
|
+
function transformFileNodesResponse(fileKey, response) {
|
|
804
|
+
const entries = Object.values(response.nodes);
|
|
805
|
+
const first = entries[0];
|
|
806
|
+
if (!first) throw new Error("No nodes returned from Figma API");
|
|
807
|
+
return {
|
|
808
|
+
fileKey,
|
|
809
|
+
name: response.name,
|
|
810
|
+
lastModified: response.lastModified,
|
|
811
|
+
version: response.version,
|
|
812
|
+
document: transformNode(first.document),
|
|
813
|
+
components: transformComponents(first.components),
|
|
814
|
+
styles: transformStyles(first.styles)
|
|
815
|
+
};
|
|
816
|
+
}
|
|
798
817
|
function transformComponents(components) {
|
|
799
818
|
const result = {};
|
|
800
819
|
for (const [id, component] of Object.entries(components)) {
|
|
@@ -952,6 +971,13 @@ async function loadFromApi(fileKey, nodeId, token) {
|
|
|
952
971
|
);
|
|
953
972
|
}
|
|
954
973
|
const client = new FigmaClient({ token: figmaToken });
|
|
974
|
+
if (nodeId) {
|
|
975
|
+
const response2 = await client.getFileNodes(fileKey, [nodeId.replace(/-/g, ":")]);
|
|
976
|
+
return {
|
|
977
|
+
file: transformFileNodesResponse(fileKey, response2),
|
|
978
|
+
nodeId
|
|
979
|
+
};
|
|
980
|
+
}
|
|
955
981
|
const response = await client.getFile(fileKey);
|
|
956
982
|
return {
|
|
957
983
|
file: transformFigmaResponse(fileKey, response),
|
|
@@ -1362,7 +1388,7 @@ function parseDesignData(data, fileKey, fileName) {
|
|
|
1362
1388
|
}
|
|
1363
1389
|
|
|
1364
1390
|
// package.json
|
|
1365
|
-
var version = "0.8.
|
|
1391
|
+
var version = "0.8.5";
|
|
1366
1392
|
var AnalysisNodeTypeSchema = z.enum([
|
|
1367
1393
|
"DOCUMENT",
|
|
1368
1394
|
"CANVAS",
|
|
@@ -2175,6 +2201,35 @@ defineRule({
|
|
|
2175
2201
|
definition: singleUseComponentDef,
|
|
2176
2202
|
check: singleUseComponentCheck
|
|
2177
2203
|
});
|
|
2204
|
+
var seenMissingDescriptionComponentIds = /* @__PURE__ */ new Set();
|
|
2205
|
+
var missingComponentDescriptionDef = {
|
|
2206
|
+
id: "missing-component-description",
|
|
2207
|
+
name: "Missing Component Description",
|
|
2208
|
+
category: "component",
|
|
2209
|
+
why: "Component descriptions in Figma are the primary channel for communicating intent, usage guidelines, and prop expectations to developers. Without them, developers must reverse-engineer purpose from visual appearance alone.",
|
|
2210
|
+
impact: "Increases implementation ambiguity, especially for icon-only components, compound components with multiple variants, and components whose names are variant key strings that give no prose context.",
|
|
2211
|
+
fix: "Open the component in Figma, select it, and add a description in the right-hand panel under the component's properties. Include: what the component is, when to use it, any accessibility or interaction notes, and the owning team or design token set if applicable."
|
|
2212
|
+
};
|
|
2213
|
+
var missingComponentDescriptionCheck = (node, context) => {
|
|
2214
|
+
if (node.type !== "INSTANCE") return null;
|
|
2215
|
+
const componentId = node.componentId;
|
|
2216
|
+
if (!componentId) return null;
|
|
2217
|
+
const componentMeta = context.file.components[componentId];
|
|
2218
|
+
if (!componentMeta) return null;
|
|
2219
|
+
if (componentMeta.description.trim() !== "") return null;
|
|
2220
|
+
if (seenMissingDescriptionComponentIds.has(componentId)) return null;
|
|
2221
|
+
seenMissingDescriptionComponentIds.add(componentId);
|
|
2222
|
+
return {
|
|
2223
|
+
ruleId: missingComponentDescriptionDef.id,
|
|
2224
|
+
nodeId: node.id,
|
|
2225
|
+
nodePath: context.path.join(" > "),
|
|
2226
|
+
message: `Component "${componentMeta.name}" has no description. Descriptions help developers understand purpose and usage.`
|
|
2227
|
+
};
|
|
2228
|
+
};
|
|
2229
|
+
defineRule({
|
|
2230
|
+
definition: missingComponentDescriptionDef,
|
|
2231
|
+
check: missingComponentDescriptionCheck
|
|
2232
|
+
});
|
|
2178
2233
|
|
|
2179
2234
|
// src/core/rules/naming/index.ts
|
|
2180
2235
|
var DEFAULT_NAME_PATTERNS = [
|