hale-commenting-system 3.8.0 → 3.8.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/package.json +5 -1
- package/scripts/integrate.js +208 -81
package/package.json
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hale-commenting-system",
|
|
3
|
-
"version": "3.8.
|
|
3
|
+
"version": "3.8.2",
|
|
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
|
"homepage": "https://www.npmjs.com/package/hale-commenting-system",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://gitlab.cee.redhat.com/juhale/hale-commenting-system.git"
|
|
9
|
+
},
|
|
6
10
|
"license": "MIT",
|
|
7
11
|
"main": "src/app/commenting-system/index.ts",
|
|
8
12
|
"types": "src/app/commenting-system/index.ts",
|
package/scripts/integrate.js
CHANGED
|
@@ -170,6 +170,36 @@ function findFile(filename, startDir = process.cwd()) {
|
|
|
170
170
|
// Detection Functions
|
|
171
171
|
// ============================================================================
|
|
172
172
|
|
|
173
|
+
function getDevServerPort() {
|
|
174
|
+
// Check environment variable first
|
|
175
|
+
if (process.env.PORT) {
|
|
176
|
+
return process.env.PORT;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Try to read from webpack.dev.js
|
|
180
|
+
try {
|
|
181
|
+
const webpackDevPath = path.join(process.cwd(), 'webpack.dev.js');
|
|
182
|
+
if (fs.existsSync(webpackDevPath)) {
|
|
183
|
+
const content = fs.readFileSync(webpackDevPath, 'utf8');
|
|
184
|
+
// Check for PORT env var pattern: process.env.PORT || '9000'
|
|
185
|
+
const envPortMatch = content.match(/process\.env\.PORT\s*\|\|\s*['"]?(\d+)['"]?/);
|
|
186
|
+
if (envPortMatch) {
|
|
187
|
+
return envPortMatch[1];
|
|
188
|
+
}
|
|
189
|
+
// Check for direct port assignment: port: PORT or port: '9000'
|
|
190
|
+
const portMatch = content.match(/port:\s*(?:PORT|['"]?(\d+)['"]?)/);
|
|
191
|
+
if (portMatch && portMatch[1]) {
|
|
192
|
+
return portMatch[1];
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
} catch {
|
|
196
|
+
// Ignore errors
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Default fallback
|
|
200
|
+
return '9000';
|
|
201
|
+
}
|
|
202
|
+
|
|
173
203
|
function detectPatternFlySeed() {
|
|
174
204
|
const cwd = process.cwd();
|
|
175
205
|
|
|
@@ -188,7 +218,11 @@ function detectPatternFlySeed() {
|
|
|
188
218
|
const packageJsonPath = path.join(cwd, 'package.json');
|
|
189
219
|
if (fs.existsSync(packageJsonPath)) {
|
|
190
220
|
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
191
|
-
const deps = {
|
|
221
|
+
const deps = {
|
|
222
|
+
...packageJson.dependencies,
|
|
223
|
+
...packageJson.devDependencies,
|
|
224
|
+
...packageJson.peerDependencies
|
|
225
|
+
};
|
|
192
226
|
hasPatternFly = !!(
|
|
193
227
|
deps['@patternfly/react-core'] ||
|
|
194
228
|
deps['@patternfly/react-icons']
|
|
@@ -927,6 +961,82 @@ devServer.app.use(express.json());
|
|
|
927
961
|
}
|
|
928
962
|
}
|
|
929
963
|
|
|
964
|
+
function fixWebpackCssLoader() {
|
|
965
|
+
const cwd = process.cwd();
|
|
966
|
+
const webpackDevPath = path.join(cwd, 'webpack.dev.js');
|
|
967
|
+
const webpackCommonPath = path.join(cwd, 'webpack.common.js');
|
|
968
|
+
|
|
969
|
+
// Try to fix CSS loader in webpack.dev.js or webpack.common.js
|
|
970
|
+
const filesToCheck = [webpackDevPath, webpackCommonPath].filter(f => fs.existsSync(f));
|
|
971
|
+
|
|
972
|
+
for (const filePath of filesToCheck) {
|
|
973
|
+
let content = fs.readFileSync(filePath, 'utf8');
|
|
974
|
+
|
|
975
|
+
// Check if CSS loader already has exclude for nested node_modules
|
|
976
|
+
if (content.includes('exclude') && content.includes('node_modules') && content.includes('node_modules')) {
|
|
977
|
+
// Already has exclude pattern, skip
|
|
978
|
+
continue;
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
// Look for CSS loader rule patterns
|
|
982
|
+
const cssLoaderPatterns = [
|
|
983
|
+
// Pattern 1: test: /\.css$/
|
|
984
|
+
/(test:\s*\/\\\.css\\\$\/[,\s]*)/,
|
|
985
|
+
// Pattern 2: test: /\.css$/i
|
|
986
|
+
/(test:\s*\/\\\.css\\\$\/i[,\s]*)/,
|
|
987
|
+
// Pattern 3: test: /\.css$/, with include
|
|
988
|
+
/(test:\s*\/\\\.css\\\$\/[,\s]*\n\s*include:)/,
|
|
989
|
+
];
|
|
990
|
+
|
|
991
|
+
let modified = false;
|
|
992
|
+
for (const pattern of cssLoaderPatterns) {
|
|
993
|
+
const match = content.match(pattern);
|
|
994
|
+
if (match) {
|
|
995
|
+
// Add exclude after the test pattern
|
|
996
|
+
const excludePattern = match[1] + '\n exclude: /node_modules\\/.*\\/node_modules\\//,';
|
|
997
|
+
content = content.replace(pattern, excludePattern);
|
|
998
|
+
modified = true;
|
|
999
|
+
break;
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
// Also try to find CSS rules in module.rules array
|
|
1004
|
+
if (!modified) {
|
|
1005
|
+
// Look for CSS rules that use stylePaths or include patterns
|
|
1006
|
+
// Pattern: test: /\.css$/, followed by include: [...stylePaths]
|
|
1007
|
+
// Match: test: /\.css$/, (with optional comma and whitespace)
|
|
1008
|
+
// newline and indentation
|
|
1009
|
+
// include: [...stylePaths]
|
|
1010
|
+
const cssRuleWithIncludePattern = /(test:\s*\/\\?\.css\$\/,?\s*\n\s*)(include:\s*\[.*?stylePaths)/s;
|
|
1011
|
+
const match = content.match(cssRuleWithIncludePattern);
|
|
1012
|
+
if (match) {
|
|
1013
|
+
// Add exclude between test and include
|
|
1014
|
+
const excludeLine = ' exclude: /node_modules\\/.*\\/node_modules\\//,\n';
|
|
1015
|
+
content = content.replace(cssRuleWithIncludePattern, match[1] + excludeLine + match[2]);
|
|
1016
|
+
modified = true;
|
|
1017
|
+
} else {
|
|
1018
|
+
// Try a more flexible pattern - look for any CSS rule with include
|
|
1019
|
+
// Match test: /\.css$/ (with or without backslash escape) followed by include:
|
|
1020
|
+
const flexiblePattern = /(test:\s*\/\\?\.css\$\/,?\s*\n\s*)(include:)/;
|
|
1021
|
+
const flexibleMatch = content.match(flexiblePattern);
|
|
1022
|
+
if (flexibleMatch) {
|
|
1023
|
+
const excludeLine = ' exclude: /node_modules\\/.*\\/node_modules\\//,\n';
|
|
1024
|
+
content = content.replace(flexiblePattern, flexibleMatch[1] + excludeLine + flexibleMatch[2]);
|
|
1025
|
+
modified = true;
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
if (modified) {
|
|
1031
|
+
fs.writeFileSync(filePath, content, 'utf8');
|
|
1032
|
+
console.log(` ✅ Updated CSS loader in ${path.basename(filePath)} to exclude nested node_modules`);
|
|
1033
|
+
return true;
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
return false;
|
|
1038
|
+
}
|
|
1039
|
+
|
|
930
1040
|
function getPackageVersion() {
|
|
931
1041
|
try {
|
|
932
1042
|
// Get the script's directory and find package.json relative to it
|
|
@@ -954,8 +1064,8 @@ function getPackageVersion() {
|
|
|
954
1064
|
function modifyIndexTsx(filePath) {
|
|
955
1065
|
const content = fs.readFileSync(filePath, 'utf8');
|
|
956
1066
|
|
|
957
|
-
// Check if already integrated
|
|
958
|
-
if (content.includes('CommentProvider') && content.includes('GitHubAuthProvider')) {
|
|
1067
|
+
// Check if already integrated (look for ProviderAuthProvider or GitHubAuthProvider for backward compat)
|
|
1068
|
+
if (content.includes('CommentProvider') && (content.includes('ProviderAuthProvider') || content.includes('GitHubAuthProvider'))) {
|
|
959
1069
|
console.log(' ⚠️ Already integrated (providers found)');
|
|
960
1070
|
return false;
|
|
961
1071
|
}
|
|
@@ -967,8 +1077,9 @@ function modifyIndexTsx(filePath) {
|
|
|
967
1077
|
});
|
|
968
1078
|
|
|
969
1079
|
let hasCommentProvider = false;
|
|
970
|
-
let
|
|
1080
|
+
let hasProviderAuthProvider = false;
|
|
971
1081
|
let hasCommentImport = false;
|
|
1082
|
+
let importSource = 'hale-commenting-system'; // Default import path
|
|
972
1083
|
let routerElement = null;
|
|
973
1084
|
|
|
974
1085
|
// Check existing imports and find Router element
|
|
@@ -977,13 +1088,21 @@ function modifyIndexTsx(filePath) {
|
|
|
977
1088
|
const source = path.node.source.value;
|
|
978
1089
|
if (source.includes('commenting-system') || source.includes('@app/commenting-system') || source.includes('hale-commenting-system')) {
|
|
979
1090
|
hasCommentImport = true;
|
|
1091
|
+
// Detect the import path being used
|
|
1092
|
+
// Always prefer 'hale-commenting-system' over '@app/commenting-system'
|
|
1093
|
+
if (source.includes('hale-commenting-system')) {
|
|
1094
|
+
importSource = 'hale-commenting-system';
|
|
1095
|
+
} else if (source.includes('@app/commenting-system')) {
|
|
1096
|
+
// If old @app/ path is found, we'll update it to hale-commenting-system
|
|
1097
|
+
importSource = 'hale-commenting-system';
|
|
1098
|
+
}
|
|
980
1099
|
// Check if providers are imported
|
|
981
1100
|
path.node.specifiers.forEach(spec => {
|
|
982
1101
|
if (spec.imported && spec.imported.name === 'CommentProvider') {
|
|
983
1102
|
hasCommentProvider = true;
|
|
984
1103
|
}
|
|
985
|
-
if (spec.imported && spec.imported.name === 'GitHubAuthProvider') {
|
|
986
|
-
|
|
1104
|
+
if (spec.imported && (spec.imported.name === 'ProviderAuthProvider' || spec.imported.name === 'GitHubAuthProvider')) {
|
|
1105
|
+
hasProviderAuthProvider = true;
|
|
987
1106
|
}
|
|
988
1107
|
});
|
|
989
1108
|
}
|
|
@@ -995,6 +1114,11 @@ function modifyIndexTsx(filePath) {
|
|
|
995
1114
|
}
|
|
996
1115
|
});
|
|
997
1116
|
|
|
1117
|
+
// Always use 'hale-commenting-system' as the package name
|
|
1118
|
+
// Don't use @app/ alias even if it exists in the file - the package
|
|
1119
|
+
// should be imported by its npm package name, not a path alias
|
|
1120
|
+
importSource = 'hale-commenting-system';
|
|
1121
|
+
|
|
998
1122
|
// Add imports if missing
|
|
999
1123
|
if (!hasCommentImport) {
|
|
1000
1124
|
// Find last import declaration
|
|
@@ -1010,24 +1134,28 @@ function modifyIndexTsx(filePath) {
|
|
|
1010
1134
|
const providerImports = types.importDeclaration(
|
|
1011
1135
|
[
|
|
1012
1136
|
types.importSpecifier(types.identifier('CommentProvider'), types.identifier('CommentProvider')),
|
|
1013
|
-
types.importSpecifier(types.identifier('
|
|
1137
|
+
types.importSpecifier(types.identifier('ProviderAuthProvider'), types.identifier('ProviderAuthProvider'))
|
|
1014
1138
|
],
|
|
1015
|
-
types.stringLiteral(
|
|
1139
|
+
types.stringLiteral(importSource)
|
|
1016
1140
|
);
|
|
1017
1141
|
|
|
1018
1142
|
ast.program.body.splice(importIndex, 0, providerImports);
|
|
1019
|
-
} else if (!hasCommentProvider || !
|
|
1020
|
-
// Update existing import
|
|
1143
|
+
} else if (!hasCommentProvider || !hasProviderAuthProvider) {
|
|
1144
|
+
// Update existing import - also fix @app/commenting-system to hale-commenting-system
|
|
1021
1145
|
traverse(ast, {
|
|
1022
1146
|
ImportDeclaration(path) {
|
|
1023
1147
|
const source = path.node.source.value;
|
|
1024
1148
|
if (source.includes('commenting-system') || source.includes('@app/commenting-system') || source.includes('hale-commenting-system')) {
|
|
1149
|
+
// Update import source to use hale-commenting-system if it's using @app/ path
|
|
1150
|
+
if (source.includes('@app/commenting-system')) {
|
|
1151
|
+
path.node.source.value = 'hale-commenting-system';
|
|
1152
|
+
}
|
|
1025
1153
|
const specifiers = path.node.specifiers || [];
|
|
1026
1154
|
if (!hasCommentProvider) {
|
|
1027
1155
|
specifiers.push(types.importSpecifier(types.identifier('CommentProvider'), types.identifier('CommentProvider')));
|
|
1028
1156
|
}
|
|
1029
|
-
if (!
|
|
1030
|
-
specifiers.push(types.importSpecifier(types.identifier('
|
|
1157
|
+
if (!hasProviderAuthProvider) {
|
|
1158
|
+
specifiers.push(types.importSpecifier(types.identifier('ProviderAuthProvider'), types.identifier('ProviderAuthProvider')));
|
|
1031
1159
|
}
|
|
1032
1160
|
path.node.specifiers = specifiers;
|
|
1033
1161
|
}
|
|
@@ -1039,28 +1167,30 @@ function modifyIndexTsx(filePath) {
|
|
|
1039
1167
|
if (routerElement) {
|
|
1040
1168
|
const routerChildren = routerElement.node.children;
|
|
1041
1169
|
|
|
1042
|
-
// Check if already wrapped
|
|
1170
|
+
// Check if already wrapped (check for ProviderAuthProvider or GitHubAuthProvider)
|
|
1043
1171
|
if (routerChildren.length > 0 &&
|
|
1044
|
-
routerChildren[0].type === 'JSXElement'
|
|
1045
|
-
|
|
1172
|
+
routerChildren[0].type === 'JSXElement') {
|
|
1173
|
+
const firstChildName = routerChildren[0].openingElement.name.name;
|
|
1174
|
+
if (firstChildName === 'ProviderAuthProvider' || firstChildName === 'GitHubAuthProvider') {
|
|
1046
1175
|
console.log(' ⚠️ Already integrated (providers found in JSX)');
|
|
1047
1176
|
return false;
|
|
1177
|
+
}
|
|
1048
1178
|
}
|
|
1049
1179
|
|
|
1050
|
-
// Create provider wrappers
|
|
1180
|
+
// Create provider wrappers in correct order: ProviderAuthProvider -> CommentProvider -> content
|
|
1051
1181
|
const commentProvider = types.jsxElement(
|
|
1052
1182
|
types.jsxOpeningElement(types.jsxIdentifier('CommentProvider'), []),
|
|
1053
1183
|
types.jsxClosingElement(types.jsxIdentifier('CommentProvider')),
|
|
1054
1184
|
routerChildren
|
|
1055
1185
|
);
|
|
1056
1186
|
|
|
1057
|
-
const
|
|
1058
|
-
types.jsxOpeningElement(types.jsxIdentifier('
|
|
1059
|
-
types.jsxClosingElement(types.jsxIdentifier('
|
|
1187
|
+
const providerAuthProvider = types.jsxElement(
|
|
1188
|
+
types.jsxOpeningElement(types.jsxIdentifier('ProviderAuthProvider'), []),
|
|
1189
|
+
types.jsxClosingElement(types.jsxIdentifier('ProviderAuthProvider')),
|
|
1060
1190
|
[commentProvider]
|
|
1061
1191
|
);
|
|
1062
1192
|
|
|
1063
|
-
routerElement.node.children = [
|
|
1193
|
+
routerElement.node.children = [providerAuthProvider];
|
|
1064
1194
|
}
|
|
1065
1195
|
|
|
1066
1196
|
const output = generate(ast, {
|
|
@@ -1195,14 +1325,14 @@ async function main() {
|
|
|
1195
1325
|
console.log('🚀 Welcome to Hale Commenting System!\n');
|
|
1196
1326
|
console.log('This commenting system allows you to:');
|
|
1197
1327
|
console.log(' • Add comments directly on your design pages');
|
|
1198
|
-
console.log(' • Sync comments with
|
|
1328
|
+
console.log(' • Sync comments with GitLab Issues (or GitHub)');
|
|
1199
1329
|
console.log(' • Link Jira tickets to pages');
|
|
1200
1330
|
console.log(' • Store design goals and context\n');
|
|
1201
1331
|
|
|
1202
|
-
console.log('Why
|
|
1203
|
-
console.log(' We use
|
|
1204
|
-
console.log(' on a page, it creates a
|
|
1205
|
-
console.log(' across devices, and be managed like any other
|
|
1332
|
+
console.log('Why GitLab?');
|
|
1333
|
+
console.log(' We use GitLab Issues to store and sync all comments. When you add a comment');
|
|
1334
|
+
console.log(' on a page, it creates a GitLab Issue. This allows comments to persist, sync');
|
|
1335
|
+
console.log(' across devices, and be managed like any other GitLab Issue.\n');
|
|
1206
1336
|
|
|
1207
1337
|
console.log('Why Jira?');
|
|
1208
1338
|
console.log(' You can link Jira tickets to specific pages or sections. This helps connect');
|
|
@@ -1263,7 +1393,7 @@ async function main() {
|
|
|
1263
1393
|
name: 'setupType',
|
|
1264
1394
|
message: 'How did you set up your PatternFly Seed project?',
|
|
1265
1395
|
choices: [
|
|
1266
|
-
{ name: 'I forked the PatternFly Seed repo
|
|
1396
|
+
{ name: 'I forked the PatternFly Seed repo', value: 'forked' },
|
|
1267
1397
|
{ name: 'I cloned the PatternFly Seed repo locally', value: 'cloned' },
|
|
1268
1398
|
{ name: 'I\'m not sure', value: 'unknown' }
|
|
1269
1399
|
]
|
|
@@ -1306,53 +1436,12 @@ async function main() {
|
|
|
1306
1436
|
console.log(`\n✅ Detected repository: ${owner}/${repo}\n`);
|
|
1307
1437
|
}
|
|
1308
1438
|
} else if (projectSetup === 'cloned') {
|
|
1309
|
-
console.log('\n📝 Since you cloned the repo, you can create your own
|
|
1310
|
-
console.log('Note: This is optional! You can test the system locally first and add
|
|
1311
|
-
|
|
1312
|
-
console.log('1. Create a new repository on GitHub');
|
|
1313
|
-
console.log('2. Add it as a remote: git remote add origin <your-repo-url>');
|
|
1314
|
-
console.log('3. Push your code: git push -u origin main\n');
|
|
1315
|
-
|
|
1316
|
-
const hasCreated = await prompt([
|
|
1317
|
-
{
|
|
1318
|
-
type: 'confirm',
|
|
1319
|
-
name: 'created',
|
|
1320
|
-
message: 'Have you created and pushed to your GitHub repository?',
|
|
1321
|
-
default: false
|
|
1322
|
-
}
|
|
1323
|
-
]);
|
|
1324
|
-
|
|
1325
|
-
if (!hasCreated.created) {
|
|
1326
|
-
console.log('\n⏭️ No problem! You can set up the GitHub repository later.');
|
|
1327
|
-
console.log(' The system will still work locally for testing.\n');
|
|
1439
|
+
console.log('\n📝 Since you cloned the repo, you can create your own repository to store comments.\n');
|
|
1440
|
+
console.log('Note: This is optional! You can test the system locally first and add integration later.\n');
|
|
1441
|
+
// Don't ask about repository here - wait until issue tracking selection
|
|
1328
1442
|
// Set placeholder values that can be updated later
|
|
1329
|
-
|
|
1443
|
+
owner = 'YOUR_USERNAME';
|
|
1330
1444
|
repo = 'YOUR_REPO_NAME';
|
|
1331
|
-
} else {
|
|
1332
|
-
// Ask for owner/repo
|
|
1333
|
-
const repoAnswers = await prompt([
|
|
1334
|
-
{
|
|
1335
|
-
type: 'input',
|
|
1336
|
-
name: 'owner',
|
|
1337
|
-
message: 'What is your GitHub username or organization name?',
|
|
1338
|
-
validate: (input) => {
|
|
1339
|
-
if (!input.trim()) return 'Owner is required';
|
|
1340
|
-
return true;
|
|
1341
|
-
}
|
|
1342
|
-
},
|
|
1343
|
-
{
|
|
1344
|
-
type: 'input',
|
|
1345
|
-
name: 'repo',
|
|
1346
|
-
message: 'What is the name of your GitHub repository?',
|
|
1347
|
-
validate: (input) => {
|
|
1348
|
-
if (!input.trim()) return 'Repository name is required';
|
|
1349
|
-
return true;
|
|
1350
|
-
}
|
|
1351
|
-
}
|
|
1352
|
-
]);
|
|
1353
|
-
owner = repoAnswers.owner;
|
|
1354
|
-
repo = repoAnswers.repo;
|
|
1355
|
-
}
|
|
1356
1445
|
} else if (projectSetup === 'unknown') {
|
|
1357
1446
|
// Try to detect from git
|
|
1358
1447
|
if (gitInfo && gitInfo.owner && gitInfo.repo) {
|
|
@@ -1394,7 +1483,7 @@ async function main() {
|
|
|
1394
1483
|
console.log(' • GitHub - Sync with GitHub Issues');
|
|
1395
1484
|
console.log(' • GitLab - Sync with GitLab Issues (supports self-hosted)');
|
|
1396
1485
|
console.log(' • Skip - Set up later (you can still use local comments)\n');
|
|
1397
|
-
|
|
1486
|
+
|
|
1398
1487
|
const platformChoice = await prompt([
|
|
1399
1488
|
{
|
|
1400
1489
|
type: 'list',
|
|
@@ -1422,8 +1511,9 @@ async function main() {
|
|
|
1422
1511
|
console.log('2. Click "New OAuth App"');
|
|
1423
1512
|
console.log('3. Fill in the form:');
|
|
1424
1513
|
console.log(' - Application name: Your app name (e.g., "My Design Comments")');
|
|
1425
|
-
|
|
1426
|
-
console.log(
|
|
1514
|
+
const devPort = getDevServerPort();
|
|
1515
|
+
console.log(` - Homepage URL: http://localhost:${devPort} (or your dev server URL)`);
|
|
1516
|
+
console.log(` - Authorization callback URL: http://localhost:${devPort}/api/github-oauth-callback`);
|
|
1427
1517
|
console.log('4. Click "Register application"');
|
|
1428
1518
|
console.log('5. Copy the Client ID and generate a Client Secret\n');
|
|
1429
1519
|
|
|
@@ -1668,15 +1758,15 @@ async function main() {
|
|
|
1668
1758
|
// Prompt for GitLab instance URL
|
|
1669
1759
|
console.log('💡 This supports both gitlab.com and self-hosted GitLab instances.');
|
|
1670
1760
|
console.log(' Examples:');
|
|
1671
|
-
console.log(' • https://gitlab.com (
|
|
1672
|
-
console.log(' • https://gitlab.
|
|
1761
|
+
console.log(' • https://gitlab.cee.redhat.com (Red Hat internal)');
|
|
1762
|
+
console.log(' • https://gitlab.com (public GitLab)\n');
|
|
1673
1763
|
|
|
1674
1764
|
const gitlabInstanceAnswer = await prompt([
|
|
1675
1765
|
{
|
|
1676
1766
|
type: 'input',
|
|
1677
1767
|
name: 'baseUrl',
|
|
1678
1768
|
message: 'GitLab instance URL:',
|
|
1679
|
-
default: 'https://gitlab.com',
|
|
1769
|
+
default: 'https://gitlab.cee.redhat.com',
|
|
1680
1770
|
validate: (input) => {
|
|
1681
1771
|
if (!input.trim()) return 'Base URL is required';
|
|
1682
1772
|
try {
|
|
@@ -1697,7 +1787,8 @@ async function main() {
|
|
|
1697
1787
|
console.log('2. Click "Add new application"');
|
|
1698
1788
|
console.log('3. Fill in the form:');
|
|
1699
1789
|
console.log(' - Name: Your app name (e.g., "My Design Comments")');
|
|
1700
|
-
|
|
1790
|
+
const devPort = getDevServerPort();
|
|
1791
|
+
console.log(` - Redirect URI: http://localhost:${devPort}/api/gitlab-oauth-callback`);
|
|
1701
1792
|
console.log(' - Confidential: ✓ (checked)');
|
|
1702
1793
|
console.log(' - Scopes: ✓ api (full API access)');
|
|
1703
1794
|
console.log('4. Click "Save application"');
|
|
@@ -1728,17 +1819,46 @@ async function main() {
|
|
|
1728
1819
|
// Prompt for project path
|
|
1729
1820
|
console.log('\nWhere do you want to store comments as GitLab Issues?');
|
|
1730
1821
|
console.log('This should be a project you have maintainer/owner access to.');
|
|
1731
|
-
console.log('
|
|
1822
|
+
console.log('');
|
|
1823
|
+
console.log('You can paste the full URL or just the path:');
|
|
1824
|
+
console.log(` • Full URL: ${baseUrl}/uxd/prototypes/rhoai`);
|
|
1825
|
+
console.log(' • Path only: uxd/prototypes/rhoai\n');
|
|
1732
1826
|
|
|
1733
1827
|
const projectPathAnswer = await prompt([
|
|
1734
1828
|
{
|
|
1735
1829
|
type: 'input',
|
|
1736
1830
|
name: 'projectPath',
|
|
1737
|
-
message: 'GitLab project path
|
|
1831
|
+
message: 'GitLab project path or full URL:',
|
|
1738
1832
|
validate: (input) => {
|
|
1739
1833
|
if (!input.trim()) return 'Project path is required';
|
|
1740
|
-
if (!input.includes('/')) return 'Project path must include at least one slash (e.g., group/project)';
|
|
1741
1834
|
return true;
|
|
1835
|
+
},
|
|
1836
|
+
filter: (input) => {
|
|
1837
|
+
// If user pasted full URL, extract the path
|
|
1838
|
+
const trimmed = input.trim();
|
|
1839
|
+
|
|
1840
|
+
// Check if it's a full URL
|
|
1841
|
+
if (trimmed.includes('http://') || trimmed.includes('https://')) {
|
|
1842
|
+
try {
|
|
1843
|
+
const url = new URL(trimmed);
|
|
1844
|
+
// Extract path after domain, remove leading/trailing slashes
|
|
1845
|
+
let path = url.pathname.replace(/^\/+|\/+$/g, '');
|
|
1846
|
+
// Remove common GitLab UI paths like /-/tree/main, /-/settings, etc.
|
|
1847
|
+
path = path.replace(/\/-\/.*$/, '');
|
|
1848
|
+
// Remove .git suffix if present
|
|
1849
|
+
path = path.replace(/\.git$/, '');
|
|
1850
|
+
return path;
|
|
1851
|
+
} catch {
|
|
1852
|
+
// If URL parsing fails, try manual extraction
|
|
1853
|
+
const match = trimmed.match(/gitlab[^/]+\/(.+?)(?:\.git|\/-\/|$)/);
|
|
1854
|
+
if (match) {
|
|
1855
|
+
return match[1].replace(/\/-\/.*$/, '').replace(/\.git$/, '');
|
|
1856
|
+
}
|
|
1857
|
+
}
|
|
1858
|
+
}
|
|
1859
|
+
|
|
1860
|
+
// If it's already a path, clean it up
|
|
1861
|
+
return trimmed.replace(/^\/+|\/+$/, '').replace(/\/-\/.*$/, '').replace(/\.git$/, '');
|
|
1742
1862
|
}
|
|
1743
1863
|
}
|
|
1744
1864
|
]);
|
|
@@ -1897,6 +2017,13 @@ async function main() {
|
|
|
1897
2017
|
// Integrate webpack middleware
|
|
1898
2018
|
console.log('\n📝 webpack.dev.js');
|
|
1899
2019
|
integrateWebpackMiddleware();
|
|
2020
|
+
|
|
2021
|
+
// Fix CSS loader to exclude nested node_modules
|
|
2022
|
+
console.log('\n📝 Fixing CSS loader configuration...');
|
|
2023
|
+
if (!fixWebpackCssLoader()) {
|
|
2024
|
+
console.log(' ⚠️ Could not auto-fix CSS loader. You may need to manually exclude nested node_modules.');
|
|
2025
|
+
console.log(' Add this to your CSS loader rule: exclude: /node_modules\\/.*\\/node_modules\\//');
|
|
2026
|
+
}
|
|
1900
2027
|
|
|
1901
2028
|
console.log('\n╔══════════════════════════════════════════════════════════╗');
|
|
1902
2029
|
console.log('║ ✅ Integration Complete! ║');
|