canicode 0.3.2 → 0.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.
- package/README.md +1 -1
- package/dist/cli/index.js +379 -14
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +10 -0
- package/dist/index.js +32 -12
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.js +338 -11
- package/dist/mcp/server.js.map +1 -1
- package/docs/CUSTOMIZATION.md +32 -1
- package/package.json +1 -1
package/dist/mcp/server.js
CHANGED
|
@@ -10,6 +10,204 @@ import { join, resolve, basename } from 'path';
|
|
|
10
10
|
import { readFile } from 'fs/promises';
|
|
11
11
|
import { homedir } from 'os';
|
|
12
12
|
|
|
13
|
+
var __defProp = Object.defineProperty;
|
|
14
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
15
|
+
var __esm = (fn, res) => function __init() {
|
|
16
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
17
|
+
};
|
|
18
|
+
var __export = (target, all) => {
|
|
19
|
+
for (var name in all)
|
|
20
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// src/monitoring/browser.ts
|
|
24
|
+
var browser_exports = {};
|
|
25
|
+
__export(browser_exports, {
|
|
26
|
+
initBrowserMonitoring: () => initBrowserMonitoring,
|
|
27
|
+
shutdownBrowserMonitoring: () => shutdownBrowserMonitoring,
|
|
28
|
+
trackBrowserError: () => trackBrowserError,
|
|
29
|
+
trackBrowserEvent: () => trackBrowserEvent
|
|
30
|
+
});
|
|
31
|
+
function getGlobal() {
|
|
32
|
+
return globalThis;
|
|
33
|
+
}
|
|
34
|
+
function injectScript(src) {
|
|
35
|
+
return new Promise((resolve4, reject) => {
|
|
36
|
+
const g = getGlobal();
|
|
37
|
+
const doc = g["document"];
|
|
38
|
+
if (!doc) {
|
|
39
|
+
resolve4();
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const script = doc["createElement"]("script");
|
|
43
|
+
script["src"] = src;
|
|
44
|
+
script["async"] = true;
|
|
45
|
+
script["onload"] = () => resolve4();
|
|
46
|
+
script["onerror"] = () => reject(new Error(`Failed to load script: ${src}`));
|
|
47
|
+
doc["head"]["appendChild"](script);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
async function initBrowserMonitoring(config2) {
|
|
51
|
+
if (config2.enabled === false) return;
|
|
52
|
+
const g = getGlobal();
|
|
53
|
+
if (!g["document"]) return;
|
|
54
|
+
monitoringEnabled = true;
|
|
55
|
+
if (config2.posthogApiKey) {
|
|
56
|
+
try {
|
|
57
|
+
await injectScript("https://us-assets.i.posthog.com/static/array.js");
|
|
58
|
+
g["posthog"]?.["init"]?.(config2.posthogApiKey, {
|
|
59
|
+
api_host: "https://us.i.posthog.com",
|
|
60
|
+
autocapture: false,
|
|
61
|
+
capture_pageview: true
|
|
62
|
+
});
|
|
63
|
+
} catch {
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (config2.sentryDsn) {
|
|
67
|
+
try {
|
|
68
|
+
await injectScript("https://browser.sentry-cdn.com/8.0.0/bundle.min.js");
|
|
69
|
+
g["Sentry"]?.["init"]?.({
|
|
70
|
+
dsn: config2.sentryDsn,
|
|
71
|
+
environment: config2.environment ?? "web",
|
|
72
|
+
release: config2.version,
|
|
73
|
+
tracesSampleRate: 0
|
|
74
|
+
});
|
|
75
|
+
} catch {
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function trackBrowserEvent(event, properties) {
|
|
80
|
+
if (!monitoringEnabled) return;
|
|
81
|
+
try {
|
|
82
|
+
getGlobal()["posthog"]?.["capture"]?.(event, properties);
|
|
83
|
+
} catch {
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function trackBrowserError(error, context) {
|
|
87
|
+
if (!monitoringEnabled) return;
|
|
88
|
+
try {
|
|
89
|
+
getGlobal()["Sentry"]?.["captureException"]?.(
|
|
90
|
+
error,
|
|
91
|
+
context ? { extra: context } : void 0
|
|
92
|
+
);
|
|
93
|
+
} catch {
|
|
94
|
+
}
|
|
95
|
+
try {
|
|
96
|
+
getGlobal()["posthog"]?.["capture"]?.("error", {
|
|
97
|
+
error: error.message,
|
|
98
|
+
...context
|
|
99
|
+
});
|
|
100
|
+
} catch {
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
async function shutdownBrowserMonitoring() {
|
|
104
|
+
monitoringEnabled = false;
|
|
105
|
+
}
|
|
106
|
+
var monitoringEnabled;
|
|
107
|
+
var init_browser = __esm({
|
|
108
|
+
"src/monitoring/browser.ts"() {
|
|
109
|
+
monitoringEnabled = false;
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// src/monitoring/node.ts
|
|
114
|
+
var node_exports = {};
|
|
115
|
+
__export(node_exports, {
|
|
116
|
+
initNodeMonitoring: () => initNodeMonitoring,
|
|
117
|
+
shutdownNodeMonitoring: () => shutdownNodeMonitoring,
|
|
118
|
+
trackNodeError: () => trackNodeError,
|
|
119
|
+
trackNodeEvent: () => trackNodeEvent
|
|
120
|
+
});
|
|
121
|
+
async function initNodeMonitoring(config2) {
|
|
122
|
+
if (config2.enabled === false) return;
|
|
123
|
+
monitoringEnabled2 = true;
|
|
124
|
+
commonProps = {
|
|
125
|
+
_sdk: "canicode",
|
|
126
|
+
_sdk_version: config2.version ?? "unknown",
|
|
127
|
+
_env: config2.environment ?? "unknown"
|
|
128
|
+
};
|
|
129
|
+
if (config2.posthogApiKey) {
|
|
130
|
+
try {
|
|
131
|
+
const mod = await import('posthog-node');
|
|
132
|
+
const PostHog = mod.PostHog;
|
|
133
|
+
posthogClient = new PostHog(config2.posthogApiKey, {
|
|
134
|
+
host: "https://us.i.posthog.com",
|
|
135
|
+
flushAt: 10,
|
|
136
|
+
flushInterval: 1e4
|
|
137
|
+
});
|
|
138
|
+
} catch {
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
if (config2.sentryDsn) {
|
|
142
|
+
try {
|
|
143
|
+
const mod = await import('@sentry/node');
|
|
144
|
+
sentryModule = mod;
|
|
145
|
+
sentryModule.init({
|
|
146
|
+
dsn: config2.sentryDsn,
|
|
147
|
+
environment: config2.environment ?? "cli",
|
|
148
|
+
release: config2.version,
|
|
149
|
+
tracesSampleRate: 0
|
|
150
|
+
});
|
|
151
|
+
} catch {
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
function trackNodeEvent(event, properties) {
|
|
156
|
+
if (!monitoringEnabled2 || !posthogClient) return;
|
|
157
|
+
try {
|
|
158
|
+
const captureOpts = {
|
|
159
|
+
distinctId: "anonymous",
|
|
160
|
+
event
|
|
161
|
+
};
|
|
162
|
+
captureOpts.properties = { ...commonProps, ...properties };
|
|
163
|
+
posthogClient.capture(captureOpts);
|
|
164
|
+
} catch {
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
function trackNodeError(error, context) {
|
|
168
|
+
if (!monitoringEnabled2) return;
|
|
169
|
+
try {
|
|
170
|
+
sentryModule?.captureException(error, context ? { extra: context } : void 0);
|
|
171
|
+
} catch {
|
|
172
|
+
}
|
|
173
|
+
try {
|
|
174
|
+
posthogClient?.capture({
|
|
175
|
+
distinctId: "anonymous",
|
|
176
|
+
event: "cic_error",
|
|
177
|
+
properties: { ...commonProps, error: error.message, ...context }
|
|
178
|
+
});
|
|
179
|
+
} catch {
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
async function shutdownNodeMonitoring() {
|
|
183
|
+
if (!monitoringEnabled2) return;
|
|
184
|
+
const tasks = [];
|
|
185
|
+
if (posthogClient) {
|
|
186
|
+
tasks.push(
|
|
187
|
+
posthogClient.shutdown().catch(() => {
|
|
188
|
+
})
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
if (sentryModule) {
|
|
192
|
+
tasks.push(
|
|
193
|
+
sentryModule.close(2e3).catch(() => {
|
|
194
|
+
})
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
await Promise.allSettled(tasks);
|
|
198
|
+
posthogClient = null;
|
|
199
|
+
sentryModule = null;
|
|
200
|
+
monitoringEnabled2 = false;
|
|
201
|
+
}
|
|
202
|
+
var posthogClient, sentryModule, monitoringEnabled2, commonProps;
|
|
203
|
+
var init_node = __esm({
|
|
204
|
+
"src/monitoring/node.ts"() {
|
|
205
|
+
posthogClient = null;
|
|
206
|
+
sentryModule = null;
|
|
207
|
+
monitoringEnabled2 = false;
|
|
208
|
+
commonProps = {};
|
|
209
|
+
}
|
|
210
|
+
});
|
|
13
211
|
var CategorySchema = z.enum([
|
|
14
212
|
"layout",
|
|
15
213
|
"token",
|
|
@@ -147,7 +345,7 @@ var RULE_CONFIGS = {
|
|
|
147
345
|
score: -2,
|
|
148
346
|
enabled: true,
|
|
149
347
|
options: {
|
|
150
|
-
gridBase:
|
|
348
|
+
gridBase: 4
|
|
151
349
|
}
|
|
152
350
|
},
|
|
153
351
|
"magic-number-spacing": {
|
|
@@ -155,7 +353,7 @@ var RULE_CONFIGS = {
|
|
|
155
353
|
score: -4,
|
|
156
354
|
enabled: true,
|
|
157
355
|
options: {
|
|
158
|
-
gridBase:
|
|
356
|
+
gridBase: 4
|
|
159
357
|
}
|
|
160
358
|
},
|
|
161
359
|
"raw-shadow": {
|
|
@@ -726,6 +924,12 @@ function transformNode(node) {
|
|
|
726
924
|
if ("layoutPositioning" in node && node.layoutPositioning) {
|
|
727
925
|
base.layoutPositioning = node.layoutPositioning;
|
|
728
926
|
}
|
|
927
|
+
if ("layoutSizingHorizontal" in node && node.layoutSizingHorizontal) {
|
|
928
|
+
base.layoutSizingHorizontal = node.layoutSizingHorizontal;
|
|
929
|
+
}
|
|
930
|
+
if ("layoutSizingVertical" in node && node.layoutSizingVertical) {
|
|
931
|
+
base.layoutSizingVertical = node.layoutSizingVertical;
|
|
932
|
+
}
|
|
729
933
|
if ("primaryAxisAlignItems" in node) {
|
|
730
934
|
base.primaryAxisAlignItems = node.primaryAxisAlignItems;
|
|
731
935
|
}
|
|
@@ -1018,6 +1222,15 @@ function getReportsDir() {
|
|
|
1018
1222
|
function ensureReportsDir() {
|
|
1019
1223
|
ensureDir(REPORTS_DIR);
|
|
1020
1224
|
}
|
|
1225
|
+
function getTelemetryEnabled() {
|
|
1226
|
+
return readConfig().telemetry !== false;
|
|
1227
|
+
}
|
|
1228
|
+
function getPosthogApiKey() {
|
|
1229
|
+
return process.env["POSTHOG_API_KEY"] ?? readConfig().posthogApiKey;
|
|
1230
|
+
}
|
|
1231
|
+
function getSentryDsn() {
|
|
1232
|
+
return process.env["SENTRY_DSN"] ?? readConfig().sentryDsn;
|
|
1233
|
+
}
|
|
1021
1234
|
|
|
1022
1235
|
// src/core/loader.ts
|
|
1023
1236
|
function isFigmaUrl(input) {
|
|
@@ -1453,7 +1666,7 @@ ${figmaToken ? ` <script>
|
|
|
1453
1666
|
const res = await fetch('https://api.figma.com/v1/files/' + fileKey + '/comments', {
|
|
1454
1667
|
method: 'POST',
|
|
1455
1668
|
headers: { 'X-FIGMA-TOKEN': FIGMA_TOKEN, 'Content-Type': 'application/json' },
|
|
1456
|
-
body: JSON.stringify({ message: commentBody, client_meta: { node_id: nodeId } }),
|
|
1669
|
+
body: JSON.stringify({ message: commentBody, client_meta: { node_id: nodeId, node_offset: { x: 0, y: 0 } } }),
|
|
1457
1670
|
});
|
|
1458
1671
|
if (!res.ok) throw new Error(await res.text());
|
|
1459
1672
|
btn.textContent = 'Sent \\u2713';
|
|
@@ -1707,6 +1920,83 @@ function createPromptBasedCheck(_cr) {
|
|
|
1707
1920
|
};
|
|
1708
1921
|
}
|
|
1709
1922
|
|
|
1923
|
+
// src/monitoring/events.ts
|
|
1924
|
+
var EVENT_PREFIX = "cic_";
|
|
1925
|
+
var EVENTS = {
|
|
1926
|
+
// Analysis
|
|
1927
|
+
ANALYSIS_STARTED: `${EVENT_PREFIX}analysis_started`,
|
|
1928
|
+
ANALYSIS_COMPLETED: `${EVENT_PREFIX}analysis_completed`,
|
|
1929
|
+
ANALYSIS_FAILED: `${EVENT_PREFIX}analysis_failed`,
|
|
1930
|
+
// Report
|
|
1931
|
+
REPORT_GENERATED: `${EVENT_PREFIX}report_generated`,
|
|
1932
|
+
COMMENT_POSTED: `${EVENT_PREFIX}comment_posted`,
|
|
1933
|
+
COMMENT_FAILED: `${EVENT_PREFIX}comment_failed`,
|
|
1934
|
+
// MCP
|
|
1935
|
+
MCP_TOOL_CALLED: `${EVENT_PREFIX}mcp_tool_called`,
|
|
1936
|
+
// CLI
|
|
1937
|
+
CLI_COMMAND: `${EVENT_PREFIX}cli_command`,
|
|
1938
|
+
CLI_INIT: `${EVENT_PREFIX}cli_init`
|
|
1939
|
+
};
|
|
1940
|
+
|
|
1941
|
+
// src/monitoring/index.ts
|
|
1942
|
+
var _trackEvent = () => {
|
|
1943
|
+
};
|
|
1944
|
+
var _trackError = () => {
|
|
1945
|
+
};
|
|
1946
|
+
var _shutdown = () => Promise.resolve();
|
|
1947
|
+
function isBrowser() {
|
|
1948
|
+
const g = globalThis;
|
|
1949
|
+
return typeof g["window"] !== "undefined" && typeof g["document"] !== "undefined";
|
|
1950
|
+
}
|
|
1951
|
+
async function initMonitoring(config2) {
|
|
1952
|
+
if (config2.enabled === false) return;
|
|
1953
|
+
if (!config2.posthogApiKey && !config2.sentryDsn) return;
|
|
1954
|
+
try {
|
|
1955
|
+
if (isBrowser()) {
|
|
1956
|
+
const { initBrowserMonitoring: initBrowserMonitoring2, trackBrowserEvent: trackBrowserEvent2, trackBrowserError: trackBrowserError2, shutdownBrowserMonitoring: shutdownBrowserMonitoring2 } = await Promise.resolve().then(() => (init_browser(), browser_exports));
|
|
1957
|
+
await initBrowserMonitoring2(config2);
|
|
1958
|
+
_trackEvent = trackBrowserEvent2;
|
|
1959
|
+
_trackError = trackBrowserError2;
|
|
1960
|
+
_shutdown = shutdownBrowserMonitoring2;
|
|
1961
|
+
} else {
|
|
1962
|
+
const { initNodeMonitoring: initNodeMonitoring2, trackNodeEvent: trackNodeEvent2, trackNodeError: trackNodeError2, shutdownNodeMonitoring: shutdownNodeMonitoring2 } = await Promise.resolve().then(() => (init_node(), node_exports));
|
|
1963
|
+
await initNodeMonitoring2(config2);
|
|
1964
|
+
_trackEvent = trackNodeEvent2;
|
|
1965
|
+
_trackError = trackNodeError2;
|
|
1966
|
+
_shutdown = shutdownNodeMonitoring2;
|
|
1967
|
+
}
|
|
1968
|
+
} catch {
|
|
1969
|
+
}
|
|
1970
|
+
}
|
|
1971
|
+
function trackEvent(event, properties) {
|
|
1972
|
+
try {
|
|
1973
|
+
_trackEvent(event, properties);
|
|
1974
|
+
} catch {
|
|
1975
|
+
}
|
|
1976
|
+
}
|
|
1977
|
+
function trackError(error, context) {
|
|
1978
|
+
try {
|
|
1979
|
+
_trackError(error, context);
|
|
1980
|
+
} catch {
|
|
1981
|
+
}
|
|
1982
|
+
}
|
|
1983
|
+
async function shutdownMonitoring() {
|
|
1984
|
+
try {
|
|
1985
|
+
await _shutdown();
|
|
1986
|
+
} catch {
|
|
1987
|
+
}
|
|
1988
|
+
}
|
|
1989
|
+
|
|
1990
|
+
// src/monitoring/keys.ts
|
|
1991
|
+
var POSTHOG_API_KEY = "phc_rBFeG140KqJLpUnlpYDEFgdMM6JozZeqQsf9twXf5Dq" ;
|
|
1992
|
+
var SENTRY_DSN = "https://80a836a8300b25f17ef5bbf23afb5b3a@o4511080656207872.ingest.us.sentry.io/4511080661319680" ;
|
|
1993
|
+
|
|
1994
|
+
// src/rules/excluded-names.ts
|
|
1995
|
+
var EXCLUDED_NAME_PATTERN = /(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)/i;
|
|
1996
|
+
function isExcludedName(name) {
|
|
1997
|
+
return EXCLUDED_NAME_PATTERN.test(name);
|
|
1998
|
+
}
|
|
1999
|
+
|
|
1710
2000
|
// src/rules/layout/index.ts
|
|
1711
2001
|
function isContainerNode(node) {
|
|
1712
2002
|
return node.type === "FRAME" || node.type === "GROUP" || node.type === "COMPONENT";
|
|
@@ -1748,7 +2038,6 @@ var absolutePositionInAutoLayoutDef = {
|
|
|
1748
2038
|
impact: "Element will not respond to sibling changes, may overlap unexpectedly",
|
|
1749
2039
|
fix: "Remove absolute positioning or use proper Auto Layout alignment"
|
|
1750
2040
|
};
|
|
1751
|
-
var INTENTIONAL_ABSOLUTE_PATTERNS = /^(badge|close|dismiss|overlay|float|fab|dot|indicator|corner|decoration|tag|status|notification|x|icon[-_ ]?(close|dismiss|x)|btn[-_ ]?(close|dismiss))/i;
|
|
1752
2041
|
function isSmallRelativeToParent(node, parent) {
|
|
1753
2042
|
const nodeBB = node.absoluteBoundingBox;
|
|
1754
2043
|
const parentBB = parent.absoluteBoundingBox;
|
|
@@ -1762,7 +2051,8 @@ var absolutePositionInAutoLayoutCheck = (node, context) => {
|
|
|
1762
2051
|
if (!context.parent) return null;
|
|
1763
2052
|
if (!hasAutoLayout(context.parent)) return null;
|
|
1764
2053
|
if (node.layoutPositioning !== "ABSOLUTE") return null;
|
|
1765
|
-
if (
|
|
2054
|
+
if (node.type === "VECTOR" || node.type === "BOOLEAN_OPERATION" || node.type === "LINE" || node.type === "ELLIPSE" || node.type === "STAR" || node.type === "REGULAR_POLYGON") return null;
|
|
2055
|
+
if (isExcludedName(node.name)) return null;
|
|
1766
2056
|
if (isSmallRelativeToParent(node, context.parent)) return null;
|
|
1767
2057
|
if (context.parent.type === "COMPONENT") return null;
|
|
1768
2058
|
return {
|
|
@@ -1788,10 +2078,14 @@ var fixedWidthInResponsiveContextCheck = (node, context) => {
|
|
|
1788
2078
|
if (!context.parent) return null;
|
|
1789
2079
|
if (!hasAutoLayout(context.parent)) return null;
|
|
1790
2080
|
if (!isContainerNode(node)) return null;
|
|
1791
|
-
if (node.
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
2081
|
+
if (node.layoutSizingHorizontal) {
|
|
2082
|
+
if (node.layoutSizingHorizontal !== "FIXED") return null;
|
|
2083
|
+
} else {
|
|
2084
|
+
if (node.layoutAlign === "STRETCH") return null;
|
|
2085
|
+
if (!node.absoluteBoundingBox) return null;
|
|
2086
|
+
if (node.layoutAlign !== "INHERIT") return null;
|
|
2087
|
+
}
|
|
2088
|
+
if (isExcludedName(node.name)) return null;
|
|
1795
2089
|
return {
|
|
1796
2090
|
ruleId: fixedWidthInResponsiveContextDef.id,
|
|
1797
2091
|
nodeId: node.id,
|
|
@@ -2064,7 +2358,7 @@ var inconsistentSpacingDef = {
|
|
|
2064
2358
|
fix: "Use spacing values from the design system grid (e.g., 8pt increments)"
|
|
2065
2359
|
};
|
|
2066
2360
|
var inconsistentSpacingCheck = (node, context, options) => {
|
|
2067
|
-
const gridBase = options?.["gridBase"] ?? getRuleOption("inconsistent-spacing", "gridBase",
|
|
2361
|
+
const gridBase = options?.["gridBase"] ?? getRuleOption("inconsistent-spacing", "gridBase", 4);
|
|
2068
2362
|
const paddings = [
|
|
2069
2363
|
node.paddingLeft,
|
|
2070
2364
|
node.paddingRight,
|
|
@@ -2106,7 +2400,7 @@ var magicNumberSpacingDef = {
|
|
|
2106
2400
|
fix: "Round spacing to the nearest grid value or use spacing tokens"
|
|
2107
2401
|
};
|
|
2108
2402
|
var magicNumberSpacingCheck = (node, context, options) => {
|
|
2109
|
-
const gridBase = options?.["gridBase"] ?? getRuleOption("magic-number-spacing", "gridBase",
|
|
2403
|
+
const gridBase = options?.["gridBase"] ?? getRuleOption("magic-number-spacing", "gridBase", 4);
|
|
2110
2404
|
const allSpacings = [
|
|
2111
2405
|
node.paddingLeft,
|
|
2112
2406
|
node.paddingRight,
|
|
@@ -2423,6 +2717,7 @@ var defaultNameDef = {
|
|
|
2423
2717
|
};
|
|
2424
2718
|
var defaultNameCheck = (node, context) => {
|
|
2425
2719
|
if (!node.name) return null;
|
|
2720
|
+
if (isExcludedName(node.name)) return null;
|
|
2426
2721
|
if (!isDefaultName(node.name)) return null;
|
|
2427
2722
|
return {
|
|
2428
2723
|
ruleId: defaultNameDef.id,
|
|
@@ -2445,6 +2740,7 @@ var nonSemanticNameDef = {
|
|
|
2445
2740
|
};
|
|
2446
2741
|
var nonSemanticNameCheck = (node, context) => {
|
|
2447
2742
|
if (!node.name) return null;
|
|
2743
|
+
if (isExcludedName(node.name)) return null;
|
|
2448
2744
|
if (!isNonSemanticName(node.name)) return null;
|
|
2449
2745
|
if (!node.children || node.children.length === 0) {
|
|
2450
2746
|
const shapeTypes = ["RECTANGLE", "ELLIPSE", "VECTOR", "LINE", "STAR", "REGULAR_POLYGON"];
|
|
@@ -2513,6 +2809,7 @@ var numericSuffixNameDef = {
|
|
|
2513
2809
|
};
|
|
2514
2810
|
var numericSuffixNameCheck = (node, context) => {
|
|
2515
2811
|
if (!node.name) return null;
|
|
2812
|
+
if (isExcludedName(node.name)) return null;
|
|
2516
2813
|
if (isDefaultName(node.name)) return null;
|
|
2517
2814
|
if (!hasNumericSuffix(node.name)) return null;
|
|
2518
2815
|
return {
|
|
@@ -2897,6 +3194,7 @@ Typical flow with Figma MCP:
|
|
|
2897
3194
|
customRulesPath: z.string().optional().describe("Path to custom rules JSON file")
|
|
2898
3195
|
},
|
|
2899
3196
|
async ({ designData, input, fileKey, fileName, token, preset, targetNodeId, configPath, customRulesPath }) => {
|
|
3197
|
+
trackEvent(EVENTS.MCP_TOOL_CALLED, { tool: "analyze" });
|
|
2900
3198
|
try {
|
|
2901
3199
|
let file;
|
|
2902
3200
|
let nodeId;
|
|
@@ -2942,6 +3240,13 @@ Typical flow with Figma MCP:
|
|
|
2942
3240
|
});
|
|
2943
3241
|
const openCmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
2944
3242
|
exec(`${openCmd} "${reportPath}"`);
|
|
3243
|
+
trackEvent(EVENTS.ANALYSIS_COMPLETED, {
|
|
3244
|
+
nodeCount: result.nodeCount,
|
|
3245
|
+
issueCount: result.issues.length,
|
|
3246
|
+
grade: scores.overall.grade,
|
|
3247
|
+
percentage: scores.overall.percentage,
|
|
3248
|
+
source: designData ? "mcp-data" : "url"
|
|
3249
|
+
});
|
|
2945
3250
|
const issuesByRule = {};
|
|
2946
3251
|
for (const issue of result.issues) {
|
|
2947
3252
|
const id = issue.violation.ruleId;
|
|
@@ -2971,6 +3276,13 @@ Typical flow with Figma MCP:
|
|
|
2971
3276
|
]
|
|
2972
3277
|
};
|
|
2973
3278
|
} catch (error) {
|
|
3279
|
+
trackError(
|
|
3280
|
+
error instanceof Error ? error : new Error(String(error)),
|
|
3281
|
+
{ tool: "analyze" }
|
|
3282
|
+
);
|
|
3283
|
+
trackEvent(EVENTS.ANALYSIS_FAILED, {
|
|
3284
|
+
error: error instanceof Error ? error.message : String(error)
|
|
3285
|
+
});
|
|
2974
3286
|
return {
|
|
2975
3287
|
content: [
|
|
2976
3288
|
{
|
|
@@ -3065,9 +3377,24 @@ Use this when the user asks about customization, configuration, rule settings, o
|
|
|
3065
3377
|
}
|
|
3066
3378
|
);
|
|
3067
3379
|
async function main() {
|
|
3380
|
+
const monitoringConfig = {
|
|
3381
|
+
environment: "mcp",
|
|
3382
|
+
version: pkg.version,
|
|
3383
|
+
enabled: getTelemetryEnabled()
|
|
3384
|
+
};
|
|
3385
|
+
const phKey = getPosthogApiKey() || POSTHOG_API_KEY;
|
|
3386
|
+
monitoringConfig.posthogApiKey = phKey;
|
|
3387
|
+
const sDsn = getSentryDsn() || SENTRY_DSN;
|
|
3388
|
+
monitoringConfig.sentryDsn = sDsn;
|
|
3389
|
+
await initMonitoring(monitoringConfig).catch(() => {
|
|
3390
|
+
});
|
|
3068
3391
|
const transport = new StdioServerTransport();
|
|
3069
3392
|
await server.connect(transport);
|
|
3070
3393
|
}
|
|
3394
|
+
process.on("beforeExit", () => {
|
|
3395
|
+
shutdownMonitoring().catch(() => {
|
|
3396
|
+
});
|
|
3397
|
+
});
|
|
3071
3398
|
main().catch(console.error);
|
|
3072
3399
|
//# sourceMappingURL=server.js.map
|
|
3073
3400
|
//# sourceMappingURL=server.js.map
|