hale-commenting-system 2.2.95 → 3.0.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hale-commenting-system",
3
- "version": "2.2.95",
3
+ "version": "3.0.0",
4
4
  "description": "A commenting system for PatternFly React applications that allows designers and developers to add comments directly on design pages, sync with GitHub Issues, and link Jira tickets.",
5
5
  "repository": "https://github.com/patternfly/patternfly-react-seed.git",
6
6
  "homepage": "https://www.npmjs.com/package/hale-commenting-system",
@@ -71,19 +71,20 @@
71
71
  "webpack-dev-server": "^5.2.1",
72
72
  "webpack-merge": "^6.0.1"
73
73
  },
74
+ "peerDependencies": {
75
+ "@patternfly/react-core": "^6.0.0",
76
+ "@patternfly/react-icons": "^6.0.0",
77
+ "react": "^18.0.0",
78
+ "react-dom": "^18.0.0",
79
+ "react-router-dom": "^7.0.0"
80
+ },
74
81
  "dependencies": {
75
82
  "@babel/generator": "^7.23.0",
76
83
  "@babel/parser": "^7.23.0",
77
84
  "@babel/traverse": "^7.23.0",
78
85
  "@babel/types": "^7.23.0",
79
- "@patternfly/react-core": "^6.4.0",
80
- "@patternfly/react-icons": "^6.4.0",
81
- "@patternfly/react-styles": "^6.4.0",
82
86
  "inquirer": "^8.2.6",
83
- "node-fetch": "^2.7.0",
84
- "react": "^18",
85
- "react-dom": "^18",
86
- "sirv-cli": "^3.0.0"
87
+ "node-fetch": "^2.7.0"
87
88
  },
88
89
  "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
89
90
  }
@@ -512,41 +512,6 @@ JIRA_API_TOKEN=
512
512
  }
513
513
  }
514
514
 
515
- function createCommentsComponent() {
516
- const cwd = process.cwd();
517
- const commentsDir = path.join(cwd, 'src', 'app', 'Comments');
518
- const commentsFile = path.join(commentsDir, 'Comments.tsx');
519
-
520
- // Check if already exists
521
- if (fs.existsSync(commentsFile)) {
522
- return; // Already exists, skip
523
- }
524
-
525
- // Create directory if it doesn't exist
526
- if (!fs.existsSync(commentsDir)) {
527
- fs.mkdirSync(commentsDir, { recursive: true });
528
- }
529
-
530
- // Read the Comments component from the package and modify the import
531
- // The file is in the package at src/app/Comments/Comments.tsx
532
- const scriptDir = __dirname || path.dirname(require.resolve('./integrate.js'));
533
- const packageCommentsFile = path.join(scriptDir, '..', 'src', 'app', 'Comments', 'Comments.tsx');
534
-
535
- let commentsComponentContent;
536
- if (fs.existsSync(packageCommentsFile)) {
537
- // Read from package and replace import path
538
- commentsComponentContent = fs.readFileSync(packageCommentsFile, 'utf8')
539
- .replace(/from ['"]@app\/commenting-system['"]/g, "from 'hale-commenting-system'");
540
- } else {
541
- // Fallback: create a minimal version (shouldn't happen if package is properly built)
542
- console.log(' ⚠️ Comments component not found in package, skipping creation');
543
- return;
544
- }
545
-
546
- fs.writeFileSync(commentsFile, commentsComponentContent);
547
- console.log(' ✅ Created Comments component');
548
- }
549
-
550
515
  function integrateWebpackMiddleware() {
551
516
  const cwd = process.cwd();
552
517
  const webpackDevPath = path.join(cwd, 'webpack.dev.js');
@@ -1035,19 +1000,13 @@ function modifyIndexTsx(filePath) {
1035
1000
  }
1036
1001
  }
1037
1002
 
1038
- function modifyRoutesTsx(filePath) {
1003
+ function modifyAppLayoutTsx(filePath) {
1039
1004
  const content = fs.readFileSync(filePath, 'utf8');
1040
-
1041
- // Check if Comments route already exists with actual routes
1042
- // Use a more sophisticated check that looks for the route path
1043
- if (content.includes("label: 'Comments'") || content.includes('label: "Comments"')) {
1044
- // Check if it has routes with the /comments path
1045
- if (content.includes("path: '/comments'") || content.includes('path: "/comments"')) {
1046
- console.log(' ⚠️ Already integrated (Comments route found)');
1047
- return false;
1048
- }
1049
- // If Comments group exists but has no routes, continue to add them
1050
- console.log(' ℹ️ Comments group exists but has no routes, adding route...');
1005
+
1006
+ // Check if already integrated
1007
+ if (content.includes('CommentPanel') && content.includes('CommentOverlay')) {
1008
+ console.log(' ⚠️ Already integrated (CommentPanel and CommentOverlay found)');
1009
+ return false;
1051
1010
  }
1052
1011
 
1053
1012
  try {
@@ -1056,392 +1015,87 @@ function modifyRoutesTsx(filePath) {
1056
1015
  plugins: ['typescript', 'jsx', 'decorators-legacy', 'classProperties']
1057
1016
  });
1058
1017
 
1059
- let routesArray = null;
1018
+ let hasCommentingImport = false;
1060
1019
 
1020
+ // Check if commenting system imports exist
1061
1021
  traverse(ast, {
1062
- VariableDeclarator(path) {
1063
- if (path.node.id.name === 'routes' && path.node.init.type === 'ArrayExpression') {
1064
- routesArray = path.node.init;
1022
+ ImportDeclaration(path) {
1023
+ const source = path.node.source.value;
1024
+ if (source.includes('hale-commenting-system')) {
1025
+ hasCommentingImport = true;
1065
1026
  }
1066
1027
  }
1067
1028
  });
1068
1029
 
1069
- if (routesArray) {
1070
- // Check if Comments component is imported
1071
- let hasCommentsImport = false;
1072
- let commentsImportName = 'Comments';
1073
-
1074
- traverse(ast, {
1075
- ImportDeclaration(path) {
1076
- const source = path.node.source.value;
1077
- if (source.includes('Comments') || source.includes('@app/Comments')) {
1078
- hasCommentsImport = true;
1079
- // Get the imported name
1080
- path.node.specifiers.forEach(spec => {
1081
- if (spec.type === 'ImportSpecifier' && spec.imported.name === 'Comments') {
1082
- commentsImportName = spec.local.name;
1083
- }
1084
- });
1085
- }
1086
- }
1087
- });
1088
-
1089
- // Add Comments import if missing
1090
- if (!hasCommentsImport) {
1091
- let lastImportIndex = -1;
1092
- for (let i = ast.program.body.length - 1; i >= 0; i--) {
1093
- if (ast.program.body[i].type === 'ImportDeclaration') {
1094
- lastImportIndex = i;
1095
- break;
1096
- }
1097
- }
1098
- const importIndex = lastImportIndex >= 0 ? lastImportIndex + 1 : 0;
1099
-
1100
- const commentsImport = types.importDeclaration(
1101
- [types.importSpecifier(types.identifier('Comments'), types.identifier('Comments'))],
1102
- types.stringLiteral('@app/Comments/Comments')
1103
- );
1104
-
1105
- ast.program.body.splice(importIndex, 0, commentsImport);
1106
- }
1107
-
1108
- // Check if Comments route group already exists
1109
- let existingCommentsGroup = null;
1110
- let existingCommentsRoutes = null;
1111
-
1112
- for (const element of routesArray.elements) {
1113
- if (element.type === 'ObjectExpression') {
1114
- const labelProp = element.properties.find(
1115
- prop => prop.key && prop.key.name === 'label' &&
1116
- prop.value && prop.value.value === 'Comments'
1117
- );
1118
- if (labelProp) {
1119
- existingCommentsGroup = element;
1120
- const routesProp = element.properties.find(
1121
- prop => prop.key && prop.key.name === 'routes'
1122
- );
1123
- if (routesProp && routesProp.value.type === 'ArrayExpression') {
1124
- existingCommentsRoutes = routesProp.value;
1125
- }
1126
- break;
1127
- }
1030
+ // Add imports if missing
1031
+ if (!hasCommentingImport) {
1032
+ let lastImportIndex = -1;
1033
+ for (let i = ast.program.body.length - 1; i >= 0; i--) {
1034
+ if (ast.program.body[i].type === 'ImportDeclaration') {
1035
+ lastImportIndex = i;
1036
+ break;
1128
1037
  }
1129
1038
  }
1039
+ const importIndex = lastImportIndex >= 0 ? lastImportIndex + 1 : 0;
1130
1040
 
1131
- // Create the Comments route item
1132
- const commentsRouteElement = types.jsxElement(
1133
- types.jsxOpeningElement(types.jsxIdentifier(commentsImportName), [], true),
1134
- null,
1135
- []
1041
+ const commentingImport = types.importDeclaration(
1042
+ [
1043
+ types.importSpecifier(types.identifier('CommentPanel'), types.identifier('CommentPanel')),
1044
+ types.importSpecifier(types.identifier('CommentOverlay'), types.identifier('CommentOverlay'))
1045
+ ],
1046
+ types.stringLiteral('hale-commenting-system')
1136
1047
  );
1137
1048
 
1138
- const commentsRouteItem = types.objectExpression([
1139
- types.objectProperty(types.identifier('element'), commentsRouteElement),
1140
- types.objectProperty(types.identifier('exact'), types.booleanLiteral(true)),
1141
- types.objectProperty(types.identifier('label'), types.stringLiteral('View all')),
1142
- types.objectProperty(types.identifier('path'), types.stringLiteral('/comments')),
1143
- types.objectProperty(types.identifier('title'), types.stringLiteral('Hale Commenting System | Comments'))
1144
- ]);
1145
-
1146
- if (existingCommentsGroup && existingCommentsRoutes) {
1147
- // Add route to existing Comments group
1148
- existingCommentsRoutes.elements.push(commentsRouteItem);
1149
- } else {
1150
- // Create new Comments route group
1151
- const commentsRoute = types.objectExpression([
1152
- types.objectProperty(types.identifier('label'), types.stringLiteral('Comments')),
1153
- types.objectProperty(types.identifier('routes'), types.arrayExpression([commentsRouteItem]))
1154
- ]);
1155
- routesArray.elements.push(commentsRoute);
1156
- }
1049
+ ast.program.body.splice(importIndex, 0, commentingImport);
1157
1050
  }
1158
1051
 
1159
- const output = generate(ast, {
1160
- retainLines: false,
1161
- compact: false
1162
- }, content);
1163
-
1164
- fs.writeFileSync(filePath, output.code);
1165
- return true;
1166
- } catch (error) {
1167
- console.error(` ❌ Error modifying ${filePath}:`, error.message);
1168
- return false;
1169
- }
1170
- }
1171
-
1172
- function modifyAppLayoutTsx(filePath) {
1173
- let content = fs.readFileSync(filePath, 'utf8');
1174
-
1175
- // Check if already integrated - look for the comprehensive integration
1176
- if (content.includes('useComments') && content.includes('useGitHubAuth') &&
1177
- content.includes('setCommentsEnabled') && content.includes('setFloatingWidgetMode')) {
1178
- console.log(' ⚠️ Already integrated (full commenting system controls found)');
1179
- return false;
1180
- }
1052
+ // Find Page component and wrap its children
1053
+ let pageComponentFound = false;
1054
+ traverse(ast, {
1055
+ JSXElement(path) {
1056
+ const openingElement = path.node.openingElement;
1057
+ if (openingElement.name && openingElement.name.name === 'Page') {
1058
+ pageComponentFound = true;
1059
+ const children = path.node.children;
1060
+
1061
+ // Check if already wrapped
1062
+ if (children.length > 0 &&
1063
+ children.some(child =>
1064
+ child.type === 'JSXElement' &&
1065
+ child.openingElement.name.name === 'CommentPanel')) {
1066
+ return;
1067
+ }
1181
1068
 
1182
- try {
1183
- // Step 1: Add imports using string manipulation (more reliable for complex imports)
1184
-
1185
- // Check and add PatternFly imports
1186
- const patternflyImportRegex = /from\s+['"]@patternfly\/react-core['"]/;
1187
- const patternflyMatch = content.match(patternflyImportRegex);
1188
-
1189
- if (patternflyMatch) {
1190
- // Find the import statement
1191
- const importMatch = content.match(/import\s+\{([^}]+)\}\s+from\s+['"]@patternfly\/react-core['"]/);
1192
- if (importMatch) {
1193
- const imports = importMatch[1];
1194
- // Add Switch if not present
1195
- if (!imports.includes('Switch')) {
1196
- const newImports = imports.trim() + ',\n Switch';
1197
- content = content.replace(
1198
- /import\s+\{([^}]+)\}\s+from\s+['"]@patternfly\/react-core['"]/,
1199
- `import {${newImports}\n} from '@patternfly/react-core'`
1069
+ // Create CommentOverlay element
1070
+ const commentOverlay = types.jsxElement(
1071
+ types.jsxOpeningElement(types.jsxIdentifier('CommentOverlay'), [], true),
1072
+ null,
1073
+ []
1200
1074
  );
1201
- }
1202
- }
1203
- }
1204
1075
 
1205
- // Check and add PatternFly icons imports
1206
- const iconsImportRegex = /from\s+['"]@patternfly\/react-icons['"]/;
1207
- const iconsMatch = content.match(iconsImportRegex);
1208
-
1209
- if (iconsMatch) {
1210
- const importMatch = content.match(/import\s+\{([^}]+)\}\s+from\s+['"]@patternfly\/react-icons['"]/);
1211
- if (importMatch) {
1212
- const imports = importMatch[1];
1213
- // Add icons if not present
1214
- let newImports = imports.trim();
1215
- if (!imports.includes('ExternalLinkAltIcon')) {
1216
- newImports += ', ExternalLinkAltIcon';
1217
- }
1218
- if (!imports.includes('GithubIcon')) {
1219
- newImports += ', GithubIcon';
1220
- }
1221
- if (newImports !== imports.trim()) {
1222
- content = content.replace(
1223
- /import\s+\{([^}]+)\}\s+from\s+['"]@patternfly\/react-icons['"]/,
1224
- `import { ${newImports} } from '@patternfly/react-icons'`
1076
+ // Create CommentPanel wrapping existing children
1077
+ const commentPanel = types.jsxElement(
1078
+ types.jsxOpeningElement(types.jsxIdentifier('CommentPanel'), []),
1079
+ types.jsxClosingElement(types.jsxIdentifier('CommentPanel')),
1080
+ [commentOverlay, ...children]
1225
1081
  );
1226
- }
1227
- }
1228
- }
1229
1082
 
1230
- // Add commenting system imports
1231
- if (!content.includes('hale-commenting-system')) {
1232
- // Find where to insert (after other imports)
1233
- const lastImportMatch = content.match(/import[^;]*;(?=\s*(?:interface|const|export|function))/g);
1234
- if (lastImportMatch) {
1235
- const lastImport = lastImportMatch[lastImportMatch.length - 1];
1236
- const insertPos = content.indexOf(lastImport) + lastImport.length;
1237
- const commentingImport = `\nimport { CommentOverlay, CommentPanel, useComments, useGitHubAuth } from "hale-commenting-system";`;
1238
- content = content.slice(0, insertPos) + commentingImport + content.slice(insertPos);
1239
- }
1240
- } else {
1241
- // Update existing import to include all needed items
1242
- const commentingImportMatch = content.match(/import\s+\{([^}]+)\}\s+from\s+["']hale-commenting-system["']/);
1243
- if (commentingImportMatch) {
1244
- const imports = commentingImportMatch[1];
1245
- let newImports = imports.split(',').map(i => i.trim());
1246
-
1247
- const needed = ['CommentOverlay', 'CommentPanel', 'useComments', 'useGitHubAuth'];
1248
- needed.forEach(item => {
1249
- if (!newImports.includes(item)) {
1250
- newImports.push(item);
1251
- }
1252
- });
1253
-
1254
- content = content.replace(
1255
- /import\s+\{[^}]+\}\s+from\s+["']hale-commenting-system["']/,
1256
- `import { ${newImports.join(', ')} } from "hale-commenting-system"`
1257
- );
1258
- }
1259
- }
1260
-
1261
- // Step 2: Add hooks to the component
1262
- // Find the AppLayout function/component
1263
- const componentMatch = content.match(/(const\s+AppLayout[^=]+=\s*\([^)]*\)\s*=>\s*\{)/);
1264
- if (componentMatch) {
1265
- const componentStart = content.indexOf(componentMatch[0]);
1266
- const afterComponentStart = componentStart + componentMatch[0].length;
1267
-
1268
- // Check if hooks are already added
1269
- if (!content.includes('const { commentsEnabled, setCommentsEnabled')) {
1270
- // Find where to insert hooks (after existing useState declarations)
1271
- const stateMatch = content.slice(afterComponentStart).match(/const\s+\[[^\]]+\]\s*=\s*React\.useState/);
1272
- let hookInsertPos;
1273
-
1274
- if (stateMatch) {
1275
- const statePos = content.indexOf(stateMatch[0], afterComponentStart);
1276
- const semicolonPos = content.indexOf(';', statePos);
1277
- hookInsertPos = semicolonPos + 1;
1278
- } else {
1279
- hookInsertPos = afterComponentStart;
1083
+ path.node.children = [commentPanel];
1280
1084
  }
1281
-
1282
- const hooks = `
1283
- const { commentsEnabled, setCommentsEnabled, drawerPinnedOpen, setDrawerPinnedOpen, floatingWidgetMode, setFloatingWidgetMode } = useComments();
1284
- const { isAuthenticated, user, login, logout } = useGitHubAuth();
1285
- `;
1286
- content = content.slice(0, hookInsertPos) + hooks + content.slice(hookInsertPos);
1287
1085
  }
1288
- }
1289
-
1290
- // Step 3: Add the special renderNavGroup logic
1291
- // Replace the simple arrow function with a block function that has special Comments handling
1292
- if (!content.includes("group.label === 'Comments'")) {
1293
- // Find the renderNavGroup function - handle both arrow expression () => (...) and block () => {...}
1294
- const arrowFuncMatch = content.match(/const\s+renderNavGroup\s*=\s*\(([^)]+)\)\s*=>\s*\(/);
1295
-
1296
- if (arrowFuncMatch) {
1297
- const params = arrowFuncMatch[1];
1298
-
1299
- // Find the entire function including the closing parenthesis and semicolon
1300
- const funcStart = content.indexOf(arrowFuncMatch[0]);
1301
- const afterArrow = funcStart + arrowFuncMatch[0].length;
1302
-
1303
- // Find matching closing paren and semicolon
1304
- let depth = 1;
1305
- let endPos = afterArrow;
1306
- for (let i = afterArrow; i < content.length; i++) {
1307
- if (content.charAt(i) === '(') depth++;
1308
- if (content.charAt(i) === ')') {
1309
- depth--;
1310
- if (depth === 0) {
1311
- // Found the closing paren, now find the semicolon
1312
- endPos = i + 1;
1313
- while (endPos < content.length && content.charAt(endPos).trim() === '') endPos++;
1314
- if (content.charAt(endPos) === ';') endPos++;
1315
- break;
1316
- }
1317
- }
1318
- }
1319
-
1320
- // Extract the original NavExpandable JSX (we'll use it as the default case)
1321
- const originalBody = content.slice(funcStart + arrowFuncMatch[0].length - 1, endPos - 1); // Remove opening ( and closing );
1322
-
1323
- // Create the new block function
1324
- const newFunction = `const renderNavGroup = (${params}) => {
1325
- // Special handling for Comments group
1326
- if (group.label === 'Comments') {
1327
- return (
1328
- <NavExpandable
1329
- key={\`\${group.label}-\${groupIndex}\`}
1330
- id={\`\${group.label}-\${groupIndex}\`}
1331
- title="Hale Commenting System"
1332
- isActive={group.routes.some((route) => route.path === location.pathname)}
1333
- >
1334
- <NavItem
1335
- onClick={(e) => {
1336
- e.stopPropagation();
1337
- setFloatingWidgetMode(!floatingWidgetMode);
1338
- if (!floatingWidgetMode) {
1339
- setDrawerPinnedOpen(false);
1340
- }
1341
- }}
1342
- style={{ cursor: 'pointer' }}
1343
- >
1344
- <div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
1345
- <ExternalLinkAltIcon />
1346
- <span>{floatingWidgetMode ? 'Close widget' : 'Pop out'}</span>
1347
- </div>
1348
- </NavItem>
1349
- <NavItem>
1350
- <div
1351
- data-comment-controls
1352
- style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', paddingRight: '1rem' }}
1353
- >
1354
- <span>Enable Comments</span>
1355
- <Switch
1356
- id="comments-enabled-switch"
1357
- isChecked={commentsEnabled}
1358
- onChange={(_event, checked) => {
1359
- setCommentsEnabled(checked);
1360
- if (checked) {
1361
- setDrawerPinnedOpen(true);
1362
- }
1363
- }}
1364
- aria-label="Enable or disable comments"
1365
- />
1366
- </div>
1367
- </NavItem>
1368
- <NavItem>
1369
- <div
1370
- data-comment-controls
1371
- style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', paddingRight: '1rem' }}
1372
- >
1373
- <span>Page info drawer</span>
1374
- <Switch
1375
- id="page-info-drawer-switch"
1376
- isChecked={drawerPinnedOpen}
1377
- onChange={(_event, checked) => setDrawerPinnedOpen(checked)}
1378
- aria-label="Pin page info drawer open"
1379
- />
1380
- </div>
1381
- </NavItem>
1382
- <NavItem>
1383
- <div
1384
- data-comment-controls
1385
- style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', paddingRight: '1rem' }}
1386
- >
1387
- {isAuthenticated ? (
1388
- <div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
1389
- <span style={{ display: 'inline-flex', alignItems: 'center', gap: '6px' }}>
1390
- <GithubIcon />
1391
- {user?.login ? \`@\${user.login}\` : 'Signed in'}
1392
- </span>
1393
- <Button variant="link" isInline onClick={logout}>
1394
- Sign out
1395
- </Button>
1396
- </div>
1397
- ) : (
1398
- <Button variant="link" isInline icon={<GithubIcon />} onClick={login}>
1399
- Sign in with GitHub
1400
- </Button>
1401
- )}
1402
- </div>
1403
- </NavItem>
1404
- {group.routes.map((route, idx) => route.label && renderNavItem(route, idx))}
1405
- </NavExpandable>
1406
- );
1407
- }
1408
-
1409
- // Default handling for other groups
1410
- return ${originalBody};
1411
- };`;
1086
+ });
1412
1087
 
1413
- // Replace the old function with the new one
1414
- content = content.slice(0, funcStart) + newFunction + content.slice(endPos);
1415
- }
1088
+ if (!pageComponentFound) {
1089
+ console.error(' ❌ Could not find Page component in AppLayout.tsx');
1090
+ return false;
1416
1091
  }
1417
1092
 
1418
- // Step 4: Wrap Page children if not already done
1419
- if (!content.includes('<CommentPanel>')) {
1420
- // Find the return statement with Page
1421
- const pageMatch = content.match(/<Page[^>]*>/);
1422
- if (pageMatch) {
1423
- const pageStart = content.indexOf(pageMatch[0]);
1424
- const pageEnd = content.indexOf('</Page>', pageStart);
1425
-
1426
- if (pageEnd > pageStart) {
1427
- // Extract children between Page tags
1428
- const pageOpenTagEnd = content.indexOf('>', pageStart) + 1;
1429
- const children = content.slice(pageOpenTagEnd, pageEnd);
1430
-
1431
- // Wrap with CommentPanel and add CommentOverlay
1432
- const wrappedChildren = `
1433
- <CommentPanel>
1434
- <CommentOverlay />
1435
- ${children.trim()}
1436
- </CommentPanel>
1437
- `;
1438
-
1439
- content = content.slice(0, pageOpenTagEnd) + wrappedChildren + content.slice(pageEnd);
1440
- }
1441
- }
1442
- }
1093
+ const output = generate(ast, {
1094
+ retainLines: false,
1095
+ compact: false
1096
+ }, content);
1443
1097
 
1444
- fs.writeFileSync(filePath, content);
1098
+ fs.writeFileSync(filePath, output.code);
1445
1099
  return true;
1446
1100
  } catch (error) {
1447
1101
  console.error(` ❌ Error modifying ${filePath}:`, error.message);
@@ -1821,15 +1475,13 @@ async function main() {
1821
1475
 
1822
1476
  // Step 5: Integrate into project
1823
1477
  console.log('\n🔧 Step 5: Integrating into PatternFly Seed project...\n');
1824
-
1478
+
1825
1479
  console.log('This will modify the following files:');
1826
1480
  console.log(' • src/app/index.tsx');
1827
- console.log(' • src/app/routes.tsx');
1828
1481
  console.log(' • src/app/AppLayout/AppLayout.tsx');
1829
1482
  console.log(' • webpack.dev.js\n');
1830
1483
 
1831
1484
  const indexPath = findFile('index.tsx');
1832
- const routesPath = findFile('routes.tsx');
1833
1485
  const appLayoutPath = findFile('AppLayout/AppLayout.tsx') || findFile('AppLayout.tsx');
1834
1486
 
1835
1487
  if (!indexPath) {
@@ -1837,11 +1489,6 @@ async function main() {
1837
1489
  rl.close();
1838
1490
  process.exit(1);
1839
1491
  }
1840
- if (!routesPath) {
1841
- console.error('❌ Could not find src/app/routes.tsx');
1842
- rl.close();
1843
- process.exit(1);
1844
- }
1845
1492
  if (!appLayoutPath) {
1846
1493
  console.error('❌ Could not find src/app/AppLayout/AppLayout.tsx');
1847
1494
  rl.close();
@@ -1862,19 +1509,6 @@ async function main() {
1862
1509
  skippedCount++;
1863
1510
  }
1864
1511
 
1865
- // Create Comments component first (needed for routes)
1866
- console.log('\n📝 Creating Comments component...');
1867
- createCommentsComponent();
1868
-
1869
- // Modify routes.tsx
1870
- console.log(`\n📝 ${routesPath}`);
1871
- if (modifyRoutesTsx(routesPath)) {
1872
- console.log(' ✅ Added Comments route');
1873
- successCount++;
1874
- } else {
1875
- skippedCount++;
1876
- }
1877
-
1878
1512
  // Modify AppLayout.tsx
1879
1513
  console.log(`\n📝 ${appLayoutPath}`);
1880
1514
  if (modifyAppLayoutTsx(appLayoutPath)) {
@@ -16,7 +16,7 @@ export const CommentOverlay: React.FunctionComponent = () => {
16
16
  const handlePageClick = (e: MouseEvent) => {
17
17
  if (!commentsEnabled) return;
18
18
 
19
- // Check if clicking on a pin or any interactive element
19
+ // Check if clicking on a pin or any interactive element (including FloatingWidget)
20
20
  const target = e.target as HTMLElement;
21
21
  if (
22
22
  target.closest('button') ||
@@ -26,9 +26,10 @@ export const CommentOverlay: React.FunctionComponent = () => {
26
26
  target.closest('textarea') ||
27
27
  target.closest('[role="button"]') ||
28
28
  target.closest('[data-comment-controls]') ||
29
- target.closest('[data-comment-pin]')
29
+ target.closest('[data-comment-pin]') ||
30
+ target.closest('[data-floating-widget]')
30
31
  ) {
31
- return; // Don't create pin if clicking interactive elements
32
+ return; // Don't create pin if clicking interactive elements or floating widget
32
33
  }
33
34
 
34
35
  // Get the overlay container dimensions (accounts for drawer being open)