canicode 0.12.1 → 0.12.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.
package/dist/cli/index.js CHANGED
@@ -3458,6 +3458,7 @@ defineRule({
3458
3458
  });
3459
3459
  var CODE_CONNECT_SETUP_KEY = "unmapped-component:setup-detected";
3460
3460
  var CODE_CONNECT_MAPPINGS_KEY = "unmapped-component:mappings";
3461
+ var SEEN_MAIN_IDS_KEY = "unmapped-component:seen-main-ids";
3461
3462
  function codeConnectIsSetUp(context) {
3462
3463
  return getAnalysisState(context, CODE_CONNECT_SETUP_KEY, () => {
3463
3464
  return existsSync(join(process.cwd(), "figma.config.json"));
@@ -3470,6 +3471,9 @@ function codeConnectMappings(context) {
3470
3471
  () => parseCodeConnectMappings(process.cwd())
3471
3472
  );
3472
3473
  }
3474
+ function seenMainIds(context) {
3475
+ return getAnalysisState(context, SEEN_MAIN_IDS_KEY, () => /* @__PURE__ */ new Set());
3476
+ }
3473
3477
  var unmappedComponentDef = {
3474
3478
  id: "unmapped-component",
3475
3479
  name: "Unmapped Component",
@@ -3479,20 +3483,33 @@ var unmappedComponentDef = {
3479
3483
  fix: "Run /canicode-roundtrip on this component to register a mapping. Figma's get_code_connect_map will skip if a mapping already exists."
3480
3484
  };
3481
3485
  var unmappedComponentCheck = (node, context) => {
3482
- if (node.type !== "COMPONENT" && node.type !== "COMPONENT_SET") return null;
3483
- if (isInsideInstance(context)) return null;
3484
3486
  if (!codeConnectIsSetUp(context)) return null;
3487
+ let mainId = null;
3488
+ let mainName = node.name;
3489
+ if (node.type === "COMPONENT" || node.type === "COMPONENT_SET") {
3490
+ if (isInsideInstance(context)) return null;
3491
+ mainId = node.id;
3492
+ } else if (node.type === "INSTANCE" && node.componentId) {
3493
+ mainId = node.componentId;
3494
+ const meta = context.file.components[node.componentId];
3495
+ if (meta?.name) mainName = meta.name;
3496
+ } else {
3497
+ return null;
3498
+ }
3499
+ const seen = seenMainIds(context);
3500
+ if (seen.has(mainId)) return null;
3501
+ seen.add(mainId);
3485
3502
  const mappings = codeConnectMappings(context);
3486
- if (mappings.mappedNodeIds.has(node.id)) return null;
3487
- const ack = context.findAcknowledgment(node.id, unmappedComponentDef.id);
3503
+ if (mappings.mappedNodeIds.has(mainId)) return null;
3504
+ const ack = context.findAcknowledgment(mainId, unmappedComponentDef.id);
3488
3505
  if (ack && isRuleOptOutIntent(ack.intent) && ack.intent.ruleId === unmappedComponentDef.id) {
3489
3506
  return null;
3490
3507
  }
3491
3508
  return {
3492
3509
  ruleId: unmappedComponentDef.id,
3493
- nodeId: node.id,
3510
+ nodeId: mainId,
3494
3511
  nodePath: context.path.join(" > "),
3495
- ...unmappedComponentMsg(node.name)
3512
+ ...unmappedComponentMsg(mainName)
3496
3513
  };
3497
3514
  };
3498
3515
  defineRule({
@@ -4509,7 +4526,7 @@ function computeApplyContext(violation, instanceContext) {
4509
4526
  }
4510
4527
 
4511
4528
  // package.json
4512
- var version2 = "0.12.1";
4529
+ var version2 = "0.12.2";
4513
4530
 
4514
4531
  // src/core/engine/scoring.ts
4515
4532
  var GRADE_ORDER = ["S", "A+", "A", "B+", "B", "C+", "C", "D", "F"];
@@ -7945,7 +7962,7 @@ function runCodeConnectChecks(cwd) {
7945
7962
  }
7946
7963
  var PUBLISH_CHECK_NAME = "Figma component published in a library";
7947
7964
  async function runFigmaPublishCheck(input) {
7948
- const { figmaUrl, token, fetchPublishedComponents } = input;
7965
+ const { figmaUrl, token, fetchPublishedComponents, fetchNodeType } = input;
7949
7966
  let parsed;
7950
7967
  try {
7951
7968
  parsed = parseFigmaUrl(figmaUrl);
@@ -8011,6 +8028,23 @@ async function runFigmaPublishCheck(input) {
8011
8028
  detail: `${match.name} (${match.node_id})`
8012
8029
  };
8013
8030
  }
8031
+ if (fetchNodeType) {
8032
+ let nodeType;
8033
+ try {
8034
+ nodeType = await fetchNodeType(parsed.fileKey, canonicalNodeId);
8035
+ } catch {
8036
+ nodeType = void 0;
8037
+ }
8038
+ if (nodeType && nodeType !== "COMPONENT" && nodeType !== "COMPONENT_SET") {
8039
+ return {
8040
+ name: PUBLISH_CHECK_NAME,
8041
+ pass: false,
8042
+ inconclusive: true,
8043
+ detail: `node ${canonicalNodeId} is type ${nodeType} \u2014 Code Connect mapping is per-component`,
8044
+ remediation: "Step 7 (Code Connect close-out) skips on screen-level scope anyway. To verify a specific component, re-invoke doctor with that component's URL."
8045
+ };
8046
+ }
8047
+ }
8014
8048
  return {
8015
8049
  name: PUBLISH_CHECK_NAME,
8016
8050
  pass: false,
@@ -8058,7 +8092,11 @@ function registerDoctor(cli2) {
8058
8092
  const publishCheck = await runFigmaPublishCheck({
8059
8093
  figmaUrl: options.figmaUrl,
8060
8094
  token,
8061
- fetchPublishedComponents: client ? (fileKey) => client.getPublishedComponents(fileKey) : void 0
8095
+ fetchPublishedComponents: client ? (fileKey) => client.getPublishedComponents(fileKey) : void 0,
8096
+ fetchNodeType: client ? async (fileKey, nodeId) => {
8097
+ const response = await client.getFileNodes(fileKey, [nodeId]);
8098
+ return response.nodes[nodeId]?.document.type;
8099
+ } : void 0
8062
8100
  });
8063
8101
  results.push(publishCheck);
8064
8102
  }