From e29fe06f0a25ee9e6a00ecd88f46c1d4074e9927 Mon Sep 17 00:00:00 2001 From: Matt Nolting Date: Wed, 19 Mar 2025 16:07:03 -0400 Subject: [PATCH 1/2] feat(code-connect-urls) --- packages/react-core/.gitignore | 3 +- .../components/AboutModal.figma.tsx | 22 +++++++++++++ packages/react-core/codeConnect/config.json | 4 +++ packages/react-core/figma.config.json | 33 +++++++++++++++++++ packages/react-core/package.json | 4 ++- 5 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 packages/react-core/codeConnect/components/AboutModal.figma.tsx create mode 100644 packages/react-core/codeConnect/config.json create mode 100644 packages/react-core/figma.config.json diff --git a/packages/react-core/.gitignore b/packages/react-core/.gitignore index 77cfc55e590..c85b6f8bc3e 100644 --- a/packages/react-core/.gitignore +++ b/packages/react-core/.gitignore @@ -2,4 +2,5 @@ /deprecated /components /layouts -/helpers \ No newline at end of file +/helpers +yarn.lock diff --git a/packages/react-core/codeConnect/components/AboutModal.figma.tsx b/packages/react-core/codeConnect/components/AboutModal.figma.tsx new file mode 100644 index 00000000000..0703ae203c2 --- /dev/null +++ b/packages/react-core/codeConnect/components/AboutModal.figma.tsx @@ -0,0 +1,22 @@ +import React from "react" +import { AboutModal } from "./AboutModal" +import figma from "@figma/code-connect" + +/** + * -- This file was auto-generated by Code Connect -- + * `props` includes a mapping from Figma properties and variants to + * suggested values. You should update this to match the props of your + * code component, and update the `example` function to return the + * code example you'd like to see in Figma + */ + +figma.connect( + AboutModal, + "[object Object]2879-13973", + { + props: { + productName: figma.string("Product name"), + }, + example: (props) => , + }, +) diff --git a/packages/react-core/codeConnect/config.json b/packages/react-core/codeConnect/config.json new file mode 100644 index 00000000000..717c0d09c84 --- /dev/null +++ b/packages/react-core/codeConnect/config.json @@ -0,0 +1,4 @@ +{ + "figmaBaseUrl": "https://www.figma.com/design/VMEX8Xg2nzhBX8rfBx53jp/branch/H3LonYnwH26v9zNEa2SXFk/PatternFly-6%3A-Components", + "defaultNodeId": "1-196" +} \ No newline at end of file diff --git a/packages/react-core/figma.config.json b/packages/react-core/figma.config.json new file mode 100644 index 00000000000..9697dee1a5f --- /dev/null +++ b/packages/react-core/figma.config.json @@ -0,0 +1,33 @@ +{ + "codeConnect": { + "parser": "react", + "label": "PF-React", + "include": [ + "components/*.tsx", + "icons/generated/*.tsx", + "icons/**/*.tsx", + "icons/*.tsx", + "icons/IconWrapper.figma.tsx", + "icons/icons.figma.tsx" + ], + "paths": { + "../generated": ["icons/generated"], + "../src/components/Icon": ["src/components/Icon"] + }, + "aliases": { + "@patternfly/react-core": "." + }, + "options": { + "instanceSwapper": { + "enabled": true + }, + "development": { + "enabled": true, + "verbose": true + }, + "production": { + "enabled": false + } + } + } +} \ No newline at end of file diff --git a/packages/react-core/package.json b/packages/react-core/package.json index a970820a5a7..e42fdcffc27 100644 --- a/packages/react-core/package.json +++ b/packages/react-core/package.json @@ -43,7 +43,9 @@ "build:single:packages": "node ../../scripts/build-single-packages.mjs --config single-packages.config.json", "clean": "rimraf dist components layouts helpers next deprecated", "generate": "node scripts/copyStyles.mjs", - "subpaths": "node ../../scripts/exportSubpaths.mjs --config subpaths.config.json" + "subpaths": "node ../../scripts/exportSubpaths.mjs --config subpaths.config.json", + "figma:watchUrls": "node codeConnect/scripts/figma-url-watcher.mjs", + "figma:fixUrls": "node codeConnect/scripts/figma-url-fixer.mjs" }, "dependencies": { "@patternfly/react-icons": "workspace:^", From 7a6a5f0221885c30d903c05c0d3d537429b2149d Mon Sep 17 00:00:00 2001 From: Matt Nolting Date: Mon, 24 Mar 2025 10:26:33 -0400 Subject: [PATCH 2/2] feat(code-connect-urls): udpated dependecies --- .../components/AboutModal.figma.tsx | 36 +++--- packages/react-core/codeConnect/config.json | 2 +- .../codeConnect/scripts/figma-url-fixer.mjs | 116 ++++++++++++++++++ .../codeConnect/scripts/figma-url-watcher.mjs | 79 ++++++++++++ packages/react-core/figma.config.json | 2 +- packages/react-core/package.json | 11 +- 6 files changed, 221 insertions(+), 25 deletions(-) create mode 100644 packages/react-core/codeConnect/scripts/figma-url-fixer.mjs create mode 100644 packages/react-core/codeConnect/scripts/figma-url-watcher.mjs diff --git a/packages/react-core/codeConnect/components/AboutModal.figma.tsx b/packages/react-core/codeConnect/components/AboutModal.figma.tsx index 0703ae203c2..e0f960b8133 100644 --- a/packages/react-core/codeConnect/components/AboutModal.figma.tsx +++ b/packages/react-core/codeConnect/components/AboutModal.figma.tsx @@ -1,22 +1,18 @@ -import React from "react" -import { AboutModal } from "./AboutModal" -import figma from "@figma/code-connect" +// import React from 'react'; +// import { AboutModal } from './AboutModal'; +// import figma from '@figma/code-connect'; -/** - * -- This file was auto-generated by Code Connect -- - * `props` includes a mapping from Figma properties and variants to - * suggested values. You should update this to match the props of your - * code component, and update the `example` function to return the - * code example you'd like to see in Figma - */ +// /** +// * -- This file was auto-generated by Code Connect -- +// * `props` includes a mapping from Figma properties and variants to +// * suggested values. You should update this to match the props of your +// * code component, and update the `example` function to return the +// * code example you'd like to see in Figma +// */ -figma.connect( - AboutModal, - "[object Object]2879-13973", - { - props: { - productName: figma.string("Product name"), - }, - example: (props) => , - }, -) +// figma.connect(AboutModal, '[object Object]2879-13973', { +// props: { +// productName: figma.string('Product name') +// }, +// example: (props) => +// }); diff --git a/packages/react-core/codeConnect/config.json b/packages/react-core/codeConnect/config.json index 717c0d09c84..790714d2232 100644 --- a/packages/react-core/codeConnect/config.json +++ b/packages/react-core/codeConnect/config.json @@ -1,4 +1,4 @@ { "figmaBaseUrl": "https://www.figma.com/design/VMEX8Xg2nzhBX8rfBx53jp/branch/H3LonYnwH26v9zNEa2SXFk/PatternFly-6%3A-Components", "defaultNodeId": "1-196" -} \ No newline at end of file +} diff --git a/packages/react-core/codeConnect/scripts/figma-url-fixer.mjs b/packages/react-core/codeConnect/scripts/figma-url-fixer.mjs new file mode 100644 index 00000000000..4e29b858157 --- /dev/null +++ b/packages/react-core/codeConnect/scripts/figma-url-fixer.mjs @@ -0,0 +1,116 @@ +/* eslint-disable no-console */ +import fs from 'fs/promises'; +import { glob } from 'glob'; +import figmaBaseUrl from '../config.json' assert { type: 'json' }; + +/** + * Process a single file to fix Figma URLs with detailed debugging + */ +export async function processFigmaFile(filePath) { + try { + console.log(`\nProcessing file: ${filePath}`); + const content = await fs.readFile(filePath, 'utf8'); + let modified = false; + + // Find all figma.connect calls with string literals as second parameter + // Updated regex to be more flexible with whitespace and formatting + const figmaConnectRegex = /figma\.connect\(\s*[^,]+,\s*(['"])([^'"]+)\1/g; + let match; + let matchCount = 0; + + // Test the content for any figma.connect calls + const hasConnect = content.includes('figma.connect'); + console.log(`Contains figma.connect calls: ${hasConnect}`); + + if (!hasConnect) { + return false; + } + + // Process all matches + while ((match = figmaConnectRegex.exec(content)) !== null) { + matchCount++; + const [fullMatch, quotes, url] = match; + console.log(`\nMatch #${matchCount} found: ${fullMatch}`); + console.log(`URL extracted: ${url}`); + + // Only process if the URL doesn't already have the correct root + const needsUpdate = !url.startsWith(figmaBaseUrl); + console.log(`URL needs update: ${needsUpdate}`); + + if (needsUpdate) { + // Extract node ID from current URL + let nodeId = null; + + // Try to extract from node-id parameter + const nodeIdMatch = url.match(/node-id=([^&]+)/); + if (nodeIdMatch) { + nodeId = nodeIdMatch[1]; + console.log(`Found node-id in URL parameter: ${nodeId}`); + } else { + // Try to extract from end of URL (format: digits-digits) + const pathParts = url.split('/'); + const lastPart = pathParts[pathParts.length - 1]; + if (/^\d+-\d+$/.test(lastPart)) { + nodeId = lastPart; + console.log(`Found node-id at end of URL: ${nodeId}`); + } + } + + // Only update if we successfully extracted a node ID + if (nodeId) { + const newUrl = `${figmaBaseUrl}${nodeId}`; + console.log(`New URL will be: ${newUrl}`); + + // Create new content by replacing the old URL with the new one + const updatedContent = content.replace(fullMatch, fullMatch.replace(url, newUrl)); + + // Check if replacement actually changed anything + if (updatedContent !== content) { + console.log(`Successfully updated URL in content`); + await fs.writeFile(filePath, updatedContent, 'utf8'); + console.log(`Updated file: ${filePath}`); + modified = true; + } else { + console.log(`Warning: Replacement had no effect on content`); + } + } else { + console.log(`Could not extract node ID from URL: ${url}`); + } + } + } + + console.log(`Total matches found: ${matchCount}`); + return modified; + } catch (error) { + console.error(`Error processing ${filePath}:`, error); + return false; + } +} + +// Simple test function that processes one file +export async function testProcessFile(filePath) { + console.log('Running test on file:', filePath); + const result = await processFigmaFile(filePath); + console.log('Processing result:', result); +} + +// If this file is run directly, execute the fix +if (import.meta.url === `file://${process.argv[1]}`) { + const testFile = process.argv[2]; + + if (testFile) { + // Test a specific file if provided + testProcessFile(testFile); + } else { + // Otherwise, find and process all files + console.log('Finding all .figma.tsx files...'); + glob('**/*.figma.tsx', { + ignore: ['**/node_modules/**', '**/dist/**'] + }).then((files) => { + console.log(`Found ${files.length} files to process`); + if (files.length > 0) { + testProcessFile(files[0]); // Test with the first file found + } + }); + } +} diff --git a/packages/react-core/codeConnect/scripts/figma-url-watcher.mjs b/packages/react-core/codeConnect/scripts/figma-url-watcher.mjs new file mode 100644 index 00000000000..e945474eb74 --- /dev/null +++ b/packages/react-core/codeConnect/scripts/figma-url-watcher.mjs @@ -0,0 +1,79 @@ +/* eslint-disable no-console */ +import { glob } from 'glob'; +import chokidar from 'chokidar'; +import { processFigmaFile } from './figma-url-fixer.mjs'; +import figmaBaseUrl from '../config.json' assert { type: 'json' }; + +// Figma file watcher function +async function figmaFileWather() { + console.log('Starting Figma URL watcher...'); + console.log('Current directory:', process.cwd()); + console.log('Using root URL:', figmaBaseUrl); + + // Find all .figma.tsx files directly using glob + const files = await glob('**/*.figma.tsx', { + ignore: ['**/node_modules/**', '**/dist/**', 'codeConnect/tests/**/*'], + absolute: true // Get absolute paths + }); + + console.log(`Found ${files.length} .figma.tsx files in the project:`); + + if (files.length === 0) { + console.log('No .figma.tsx files found. Please check your project structure.'); + return; + } + + // Log found files + files.forEach((file) => console.log(` - ${file}`)); + + // Process all files first + let fixedCount = 0; + for (const file of files) { + try { + const wasFixed = await processFigmaFile(file); + if (wasFixed) { + fixedCount++; + } + } catch (error) { + console.error(`Error processing ${file}:`, error.message); + } + } + + console.log(`Initial processing complete. Fixed ${fixedCount} files.`); + + // Now set up watcher for these specific files + const watcher = chokidar.watch(files, { + persistent: true, + ignoreInitial: true, // We already processed them + awaitWriteFinish: { + stabilityThreshold: 300, + pollInterval: 100 + } + }); + + // Simple file handler + const handleFile = async (filePath) => { + console.log(`File changed: ${filePath}`); + try { + await processFigmaFile(filePath); + } catch (error) { + console.error(`Error processing ${filePath}:`, error.message); + } + }; + + // Set up event handlers + watcher + .on('change', handleFile) + .on('ready', () => { + console.log('Watcher ready. Monitoring these files for changes:'); + files.forEach((file) => console.log(` - ${file}`)); + }) + .on('error', (error) => console.error(`Watcher error:`, error)); + + console.log('Watcher started. Press Ctrl+C to stop.'); +} + +// Run the figmaFileWather function +figmaFileWather().catch((error) => { + console.error('Fatal error:', error); +}); diff --git a/packages/react-core/figma.config.json b/packages/react-core/figma.config.json index 9697dee1a5f..a149dac5643 100644 --- a/packages/react-core/figma.config.json +++ b/packages/react-core/figma.config.json @@ -30,4 +30,4 @@ } } } -} \ No newline at end of file +} diff --git a/packages/react-core/package.json b/packages/react-core/package.json index e42fdcffc27..290b343b7e8 100644 --- a/packages/react-core/package.json +++ b/packages/react-core/package.json @@ -3,6 +3,7 @@ "version": "6.2.0-prerelease.34", "description": "This library provides a set of common React components for use with the PatternFly reference implementation.", "main": "dist/js/index.js", + "type": "module", "module": "dist/esm/index.js", "types": "dist/esm/index.d.ts", "typesVersions": { @@ -42,21 +43,25 @@ "build:umd": "rollup -c --environment IS_PRODUCTION", "build:single:packages": "node ../../scripts/build-single-packages.mjs --config single-packages.config.json", "clean": "rimraf dist components layouts helpers next deprecated", - "generate": "node scripts/copyStyles.mjs", - "subpaths": "node ../../scripts/exportSubpaths.mjs --config subpaths.config.json", "figma:watchUrls": "node codeConnect/scripts/figma-url-watcher.mjs", - "figma:fixUrls": "node codeConnect/scripts/figma-url-fixer.mjs" + "figma:fixUrls": "node codeConnect/scripts/figma-url-fixer.mjs", + "generate": "node scripts/copyStyles.mjs", + "subpaths": "node ../../scripts/exportSubpaths.mjs --config subpaths.config.json" }, "dependencies": { "@patternfly/react-icons": "workspace:^", "@patternfly/react-styles": "workspace:^", "@patternfly/react-tokens": "workspace:^", + "@types/glob": "^8.1.0", + "@types/node": "^22.13.5", "focus-trap": "7.6.4", + "react": "^18.2.0", "react-dropzone": "^14.3.5", "tslib": "^2.8.1" }, "devDependencies": { "@patternfly/patternfly": "6.2.0-prerelease.25", + "@figma/code-connect": "^1.3.1", "case-anything": "^3.1.2", "css": "^3.0.0", "fs-extra": "^11.3.0"