hale-commenting-system 2.2.91 → 2.2.94
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 +1 -1
- package/scripts/integrate.js +223 -85
- package/src/app/commenting-system/index.ts +6 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hale-commenting-system",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.94",
|
|
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",
|
package/scripts/integrate.js
CHANGED
|
@@ -1170,115 +1170,253 @@ function modifyRoutesTsx(filePath) {
|
|
|
1170
1170
|
}
|
|
1171
1171
|
|
|
1172
1172
|
function modifyAppLayoutTsx(filePath) {
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
// Check if already integrated
|
|
1176
|
-
if (content.includes('
|
|
1177
|
-
|
|
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)');
|
|
1178
1179
|
return false;
|
|
1179
1180
|
}
|
|
1180
1181
|
|
|
1181
1182
|
try {
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
if (
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
s.imported && (s.imported.name === 'CommentPanel' || s.local.name === 'CommentPanel')
|
|
1200
|
-
);
|
|
1201
|
-
const hasCommentOverlay = specifiers.some(s =>
|
|
1202
|
-
s.imported && (s.imported.name === 'CommentOverlay' || s.local.name === 'CommentOverlay')
|
|
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'`
|
|
1203
1200
|
);
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1204
1204
|
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
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';
|
|
1212
1217
|
}
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
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'`
|
|
1225
|
+
);
|
|
1217
1226
|
}
|
|
1218
1227
|
}
|
|
1219
|
-
}
|
|
1228
|
+
}
|
|
1220
1229
|
|
|
1221
|
-
// Add
|
|
1222
|
-
if (!
|
|
1223
|
-
// Find
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
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
|
+
);
|
|
1230
1258
|
}
|
|
1231
|
-
const importIndex = lastImportIndex >= 0 ? lastImportIndex + 1 : 0;
|
|
1232
|
-
|
|
1233
|
-
const componentImports = types.importDeclaration(
|
|
1234
|
-
[
|
|
1235
|
-
types.importSpecifier(types.identifier('CommentPanel'), types.identifier('CommentPanel')),
|
|
1236
|
-
types.importSpecifier(types.identifier('CommentOverlay'), types.identifier('CommentOverlay'))
|
|
1237
|
-
],
|
|
1238
|
-
types.stringLiteral('hale-commenting-system')
|
|
1239
|
-
);
|
|
1240
|
-
|
|
1241
|
-
ast.program.body.splice(importIndex, 0, componentImports);
|
|
1242
1259
|
}
|
|
1243
1260
|
|
|
1244
|
-
//
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
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;
|
|
1280
|
+
}
|
|
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);
|
|
1254
1287
|
}
|
|
1288
|
+
}
|
|
1255
1289
|
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1290
|
+
// Step 3: Add the special renderNavGroup logic
|
|
1291
|
+
// Find the renderNavGroup function
|
|
1292
|
+
const renderNavGroupMatch = content.match(/const\s+renderNavGroup\s*=\s*\([^)]+\)\s*=>\s*\{?/);
|
|
1293
|
+
if (renderNavGroupMatch && !content.includes("group.label === 'Comments'")) {
|
|
1294
|
+
const funcStart = content.indexOf(renderNavGroupMatch[0]);
|
|
1295
|
+
const funcStartBrace = content.indexOf('{', funcStart) || content.indexOf('(', funcStart);
|
|
1296
|
+
|
|
1297
|
+
// Insert the special Comments handling at the start of the function
|
|
1298
|
+
const specialHandling = `
|
|
1299
|
+
// Special handling for Comments group
|
|
1300
|
+
if (group.label === 'Comments') {
|
|
1301
|
+
return (
|
|
1302
|
+
<NavExpandable
|
|
1303
|
+
key={\`\${group.label}-\${groupIndex}\`}
|
|
1304
|
+
id={\`\${group.label}-\${groupIndex}\`}
|
|
1305
|
+
title="Hale Commenting System"
|
|
1306
|
+
isActive={group.routes.some((route) => route.path === location.pathname)}
|
|
1307
|
+
>
|
|
1308
|
+
<NavItem
|
|
1309
|
+
onClick={(e) => {
|
|
1310
|
+
e.stopPropagation();
|
|
1311
|
+
setFloatingWidgetMode(!floatingWidgetMode);
|
|
1312
|
+
if (!floatingWidgetMode) {
|
|
1313
|
+
setDrawerPinnedOpen(false);
|
|
1314
|
+
}
|
|
1315
|
+
}}
|
|
1316
|
+
style={{ cursor: 'pointer' }}
|
|
1317
|
+
>
|
|
1318
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
|
|
1319
|
+
<ExternalLinkAltIcon />
|
|
1320
|
+
<span>{floatingWidgetMode ? 'Close widget' : 'Pop out'}</span>
|
|
1321
|
+
</div>
|
|
1322
|
+
</NavItem>
|
|
1323
|
+
<NavItem>
|
|
1324
|
+
<div
|
|
1325
|
+
data-comment-controls
|
|
1326
|
+
style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', paddingRight: '1rem' }}
|
|
1327
|
+
>
|
|
1328
|
+
<span>Enable Comments</span>
|
|
1329
|
+
<Switch
|
|
1330
|
+
id="comments-enabled-switch"
|
|
1331
|
+
isChecked={commentsEnabled}
|
|
1332
|
+
onChange={(_event, checked) => {
|
|
1333
|
+
setCommentsEnabled(checked);
|
|
1334
|
+
if (checked) {
|
|
1335
|
+
setDrawerPinnedOpen(true);
|
|
1336
|
+
}
|
|
1337
|
+
}}
|
|
1338
|
+
aria-label="Enable or disable comments"
|
|
1339
|
+
/>
|
|
1340
|
+
</div>
|
|
1341
|
+
</NavItem>
|
|
1342
|
+
<NavItem>
|
|
1343
|
+
<div
|
|
1344
|
+
data-comment-controls
|
|
1345
|
+
style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', paddingRight: '1rem' }}
|
|
1346
|
+
>
|
|
1347
|
+
<span>Page info drawer</span>
|
|
1348
|
+
<Switch
|
|
1349
|
+
id="page-info-drawer-switch"
|
|
1350
|
+
isChecked={drawerPinnedOpen}
|
|
1351
|
+
onChange={(_event, checked) => setDrawerPinnedOpen(checked)}
|
|
1352
|
+
aria-label="Pin page info drawer open"
|
|
1353
|
+
/>
|
|
1354
|
+
</div>
|
|
1355
|
+
</NavItem>
|
|
1356
|
+
<NavItem>
|
|
1357
|
+
<div
|
|
1358
|
+
data-comment-controls
|
|
1359
|
+
style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', paddingRight: '1rem' }}
|
|
1360
|
+
>
|
|
1361
|
+
{isAuthenticated ? (
|
|
1362
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
|
|
1363
|
+
<span style={{ display: 'inline-flex', alignItems: 'center', gap: '6px' }}>
|
|
1364
|
+
<GithubIcon />
|
|
1365
|
+
{user?.login ? \`@\${user.login}\` : 'Signed in'}
|
|
1366
|
+
</span>
|
|
1367
|
+
<Button variant="link" isInline onClick={logout}>
|
|
1368
|
+
Sign out
|
|
1369
|
+
</Button>
|
|
1370
|
+
</div>
|
|
1371
|
+
) : (
|
|
1372
|
+
<Button variant="link" isInline icon={<GithubIcon />} onClick={login}>
|
|
1373
|
+
Sign in with GitHub
|
|
1374
|
+
</Button>
|
|
1375
|
+
)}
|
|
1376
|
+
</div>
|
|
1377
|
+
</NavItem>
|
|
1378
|
+
{group.routes.map((route, idx) => route.label && renderNavItem(route, idx))}
|
|
1379
|
+
</NavExpandable>
|
|
1261
1380
|
);
|
|
1381
|
+
}
|
|
1262
1382
|
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
types.jsxOpeningElement(types.jsxIdentifier('CommentPanel'), []),
|
|
1266
|
-
types.jsxClosingElement(types.jsxIdentifier('CommentPanel')),
|
|
1267
|
-
[commentOverlay, ...pageChildren]
|
|
1268
|
-
);
|
|
1383
|
+
// Default handling for other groups
|
|
1384
|
+
`;
|
|
1269
1385
|
|
|
1270
|
-
|
|
1386
|
+
content = content.slice(0, funcStartBrace + 1) + specialHandling + content.slice(funcStartBrace + 1);
|
|
1271
1387
|
}
|
|
1272
1388
|
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1389
|
+
// Step 4: Wrap Page children if not already done
|
|
1390
|
+
if (!content.includes('<CommentPanel>')) {
|
|
1391
|
+
// Find the return statement with Page
|
|
1392
|
+
const pageMatch = content.match(/<Page[^>]*>/);
|
|
1393
|
+
if (pageMatch) {
|
|
1394
|
+
const pageStart = content.indexOf(pageMatch[0]);
|
|
1395
|
+
const pageEnd = content.indexOf('</Page>', pageStart);
|
|
1396
|
+
|
|
1397
|
+
if (pageEnd > pageStart) {
|
|
1398
|
+
// Extract children between Page tags
|
|
1399
|
+
const pageOpenTagEnd = content.indexOf('>', pageStart) + 1;
|
|
1400
|
+
const children = content.slice(pageOpenTagEnd, pageEnd);
|
|
1401
|
+
|
|
1402
|
+
// Wrap with CommentPanel and add CommentOverlay
|
|
1403
|
+
const wrappedChildren = `
|
|
1404
|
+
<CommentPanel>
|
|
1405
|
+
<CommentOverlay />
|
|
1406
|
+
${children.trim()}
|
|
1407
|
+
</CommentPanel>
|
|
1408
|
+
`;
|
|
1409
|
+
|
|
1410
|
+
content = content.slice(0, pageOpenTagEnd) + wrappedChildren + content.slice(pageEnd);
|
|
1411
|
+
}
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1277
1414
|
|
|
1278
|
-
fs.writeFileSync(filePath,
|
|
1415
|
+
fs.writeFileSync(filePath, content);
|
|
1279
1416
|
return true;
|
|
1280
1417
|
} catch (error) {
|
|
1281
1418
|
console.error(` ❌ Error modifying ${filePath}:`, error.message);
|
|
1419
|
+
console.error(error.stack);
|
|
1282
1420
|
return false;
|
|
1283
1421
|
}
|
|
1284
1422
|
}
|
|
@@ -6,6 +6,12 @@ export { GitHubAuthProvider, useGitHubAuth } from './contexts/GitHubAuthContext'
|
|
|
6
6
|
export { CommentOverlay } from './components/CommentOverlay';
|
|
7
7
|
export { CommentPin } from './components/CommentPin';
|
|
8
8
|
export { CommentPanel } from './components/CommentPanel';
|
|
9
|
+
export { DetailsTab } from './components/DetailsTab';
|
|
10
|
+
export { JiraTab } from './components/JiraTab';
|
|
11
|
+
export { FloatingWidget } from './components/FloatingWidget';
|
|
12
|
+
|
|
13
|
+
// Services
|
|
14
|
+
export { githubAdapter, isGitHubConfigured } from './services/githubAdapter';
|
|
9
15
|
|
|
10
16
|
// Types
|
|
11
17
|
export type { Comment, Thread, SyncStatus, ThreadStatus } from './types';
|