{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/connect/helpers.ts"],"names":[],"mappings":"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","sourcesContent":["import { FigmaRestApi } from './figma_rest_api'\nimport * as url from 'url'\nimport { logger } from '../common/logging'\n\nconst guidRegex = /^I?[0-9]+:[0-9]+(;[0-9]+:[0-9]+)*$/\n\nexport function isComponent(node: FigmaRestApi.Node): node is FigmaRestApi.Component {\n return node.type === 'COMPONENT' || node.type === 'COMPONENT_SET'\n}\n\nexport const validateNodeId = function (id: string): string {\n const newId = id.replace('-', ':')\n if (!guidRegex.test(newId)) {\n logger.error(`Invalid figma node URL: the provided node-id \"${id}\" is invalid`)\n exitWithFeedbackMessage(1)\n }\n return newId\n}\n\nexport function parseNodeIds(figmaNodeUrls: string[]): string[] {\n const nodeIds: string[] = []\n for (const nodeURL of figmaNodeUrls) {\n const figmaNodeUrl = url.parse(nodeURL, true)\n const nodeId = figmaNodeUrl.query['node-id']\n if (nodeId && typeof nodeId === 'string') {\n const figmaNodeId = validateNodeId(nodeId)\n nodeIds.push(figmaNodeId)\n } else if (Array.isArray(nodeId)) {\n for (const id of nodeId) {\n const figmaNodeId = validateNodeId(id)\n nodeIds.push(figmaNodeId)\n }\n }\n }\n return nodeIds\n}\n\nexport function parseFileKey(figmaNodeUrl: string) {\n return figmaNodeUrl.match(/(?:file|design)\\/([a-zA-Z0-9]+)/)?.[1]\n}\n\n/**\n * Parses components from a Rest API response\n * @param document\n * @param nodeIds\n * @returns\n */\nexport function findComponentsInDocument(\n document: FigmaRestApi.Node,\n nodeIds?: string[],\n): FigmaRestApi.Component[] {\n const components: FigmaRestApi.Component[] = []\n const pages: FigmaRestApi.Node[] = document.children\n\n for (const page of pages) {\n if (page.type !== 'CANVAS') {\n continue\n }\n const pageId = page.id\n const pageName = page.name\n\n const stack: FigmaRestApi.Node[] = page.children\n\n while (stack.length > 0) {\n const node = stack.pop()!\n if (nodeIds && nodeIds.includes(node.id)) {\n if (!isComponent(node)) {\n throw new Error('Specified node is not a component or a component set')\n }\n components.push({ ...node, pageId, pageName })\n }\n if (!nodeIds && isComponent(node)) {\n components.push({ ...node, pageId, pageName })\n }\n // don't traverse into component sets\n if (Array.isArray(node.children) && !isComponent(node)) {\n stack.push(...node.children)\n }\n }\n }\n\n return components\n}\n\n/**\n * Gets the URL of a figma component\n *\n * @param component a published figma component\n * @returns a URL to the figma component\n */\nexport function figmaUrlOfComponent(component: FigmaRestApi.Component, fileKey: string) {\n const fileUrl = process.env.FILE_URL || `https://figma.com/file/`\n const nodeId = component.id.replace(':', '-')\n const urlId = nodeId.replace(':', '-')\n return `${fileUrl}${fileKey}/?node-id=${urlId}`\n}\n\n/**\n * removes the ID part of a component property name\n */\nexport function normalizePropName(name: string) {\n return name.replace(/#[0-9:]*/g, '')\n}\n\n/**\n * Applies documentUrlSubstitutions to a value. Processes longer keys first so that\n * when one key is a prefix of another (e.g. \"Input\" and \"InputMenu\"),\n * the longer match wins and avoids corrupting the result.\n */\nexport function applyDocumentUrlSubstitutions(\n value: string,\n substitutions: Record,\n): string {\n const entries = Object.entries(substitutions)\n if (entries.length === 0) return value\n // Sort by key length descending so \"InputMenu\" is applied before \"Input\"\n const sorted = [...entries].sort(([a], [b]) => b.length - a.length)\n let result = value\n for (const [from, to] of sorted) {\n result = result.replace(from, to)\n }\n return result\n}\n\n/**\n * Displays a feedback/bugs issues link before exiting\n */\nexport function exitWithFeedbackMessage(exitCode: number): never {\n logger.info('Please raise any bugs or feedback at https://github.com/figma/code-connect/issues.')\n process.exit(exitCode)\n}\n"]}