hale-commenting-system 2.0.1 → 2.0.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/README.md +14 -11
- package/cli/dist/index.js +49 -39
- package/cli/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -73,7 +73,8 @@ import { BrowserRouter as Router } from 'react-router-dom';
|
|
|
73
73
|
import {
|
|
74
74
|
CommentProvider,
|
|
75
75
|
CommentOverlay,
|
|
76
|
-
CommentDrawer
|
|
76
|
+
CommentDrawer,
|
|
77
|
+
VersionProvider
|
|
77
78
|
} from 'hale-commenting-system';
|
|
78
79
|
|
|
79
80
|
function App() {
|
|
@@ -81,18 +82,20 @@ function App() {
|
|
|
81
82
|
|
|
82
83
|
return (
|
|
83
84
|
<Router>
|
|
84
|
-
<
|
|
85
|
-
<
|
|
86
|
-
|
|
87
|
-
onThreadSelect={setSelectedThreadId}
|
|
88
|
-
>
|
|
89
|
-
<CommentOverlay
|
|
85
|
+
<VersionProvider>
|
|
86
|
+
<CommentProvider>
|
|
87
|
+
<CommentDrawer
|
|
90
88
|
selectedThreadId={selectedThreadId}
|
|
91
89
|
onThreadSelect={setSelectedThreadId}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
90
|
+
>
|
|
91
|
+
<CommentOverlay
|
|
92
|
+
selectedThreadId={selectedThreadId}
|
|
93
|
+
onThreadSelect={setSelectedThreadId}
|
|
94
|
+
/>
|
|
95
|
+
{/* Your app content */}
|
|
96
|
+
</CommentDrawer>
|
|
97
|
+
</CommentProvider>
|
|
98
|
+
</VersionProvider>
|
|
96
99
|
</Router>
|
|
97
100
|
);
|
|
98
101
|
}
|
package/cli/dist/index.js
CHANGED
|
@@ -142,7 +142,9 @@ function injectProviders(content) {
|
|
|
142
142
|
const imports = `import {
|
|
143
143
|
CommentProvider,
|
|
144
144
|
CommentOverlay,
|
|
145
|
-
CommentDrawer
|
|
145
|
+
CommentDrawer,
|
|
146
|
+
useComments,
|
|
147
|
+
VersionProvider
|
|
146
148
|
} from 'hale-commenting-system';`;
|
|
147
149
|
const importRegex = /import\s+.*?from\s+['"].*?['"];?/g;
|
|
148
150
|
const matches = content.match(importRegex);
|
|
@@ -203,6 +205,25 @@ function injectProviders(content) {
|
|
|
203
205
|
const innerContent = routerMatch[2];
|
|
204
206
|
wrappedReturn = `
|
|
205
207
|
<${routerType}>
|
|
208
|
+
<VersionProvider>
|
|
209
|
+
<CommentProvider>
|
|
210
|
+
<CommentDrawer
|
|
211
|
+
selectedThreadId={selectedThreadId}
|
|
212
|
+
onThreadSelect={setSelectedThreadId}
|
|
213
|
+
>
|
|
214
|
+
<CommentOverlay
|
|
215
|
+
selectedThreadId={selectedThreadId}
|
|
216
|
+
onThreadSelect={setSelectedThreadId}
|
|
217
|
+
/>
|
|
218
|
+
${innerContent.trim()}
|
|
219
|
+
</CommentDrawer>
|
|
220
|
+
</CommentProvider>
|
|
221
|
+
</VersionProvider>
|
|
222
|
+
</${routerType}>
|
|
223
|
+
`;
|
|
224
|
+
} else {
|
|
225
|
+
wrappedReturn = `
|
|
226
|
+
<VersionProvider>
|
|
206
227
|
<CommentProvider>
|
|
207
228
|
<CommentDrawer
|
|
208
229
|
selectedThreadId={selectedThreadId}
|
|
@@ -212,41 +233,28 @@ function injectProviders(content) {
|
|
|
212
233
|
selectedThreadId={selectedThreadId}
|
|
213
234
|
onThreadSelect={setSelectedThreadId}
|
|
214
235
|
/>
|
|
215
|
-
${
|
|
236
|
+
${originalReturn}
|
|
216
237
|
</CommentDrawer>
|
|
217
238
|
</CommentProvider>
|
|
218
|
-
|
|
219
|
-
`;
|
|
220
|
-
} else {
|
|
221
|
-
wrappedReturn = `
|
|
222
|
-
<CommentProvider>
|
|
223
|
-
<CommentDrawer
|
|
224
|
-
selectedThreadId={selectedThreadId}
|
|
225
|
-
onThreadSelect={setSelectedThreadId}
|
|
226
|
-
>
|
|
227
|
-
<CommentOverlay
|
|
228
|
-
selectedThreadId={selectedThreadId}
|
|
229
|
-
onThreadSelect={setSelectedThreadId}
|
|
230
|
-
/>
|
|
231
|
-
${originalReturn}
|
|
232
|
-
</CommentDrawer>
|
|
233
|
-
</CommentProvider>
|
|
239
|
+
</VersionProvider>
|
|
234
240
|
`;
|
|
235
241
|
}
|
|
236
242
|
} else {
|
|
237
243
|
wrappedReturn = `
|
|
238
|
-
<
|
|
239
|
-
<
|
|
240
|
-
|
|
241
|
-
onThreadSelect={setSelectedThreadId}
|
|
242
|
-
>
|
|
243
|
-
<CommentOverlay
|
|
244
|
+
<VersionProvider>
|
|
245
|
+
<CommentProvider>
|
|
246
|
+
<CommentDrawer
|
|
244
247
|
selectedThreadId={selectedThreadId}
|
|
245
248
|
onThreadSelect={setSelectedThreadId}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
249
|
+
>
|
|
250
|
+
<CommentOverlay
|
|
251
|
+
selectedThreadId={selectedThreadId}
|
|
252
|
+
onThreadSelect={setSelectedThreadId}
|
|
253
|
+
/>
|
|
254
|
+
${originalReturn}
|
|
255
|
+
</CommentDrawer>
|
|
256
|
+
</CommentProvider>
|
|
257
|
+
</VersionProvider>
|
|
250
258
|
`;
|
|
251
259
|
}
|
|
252
260
|
content = content.slice(0, returnStart) + wrappedReturn + content.slice(returnEnd);
|
|
@@ -314,7 +322,7 @@ async function initCommand(options) {
|
|
|
314
322
|
spinner.warn(result.message);
|
|
315
323
|
console.log(chalk3.yellow("\n\u26A0\uFE0F Could not automatically integrate the commenting system.\n"));
|
|
316
324
|
console.log(chalk3.white("Please manually add the following to your App component:\n"));
|
|
317
|
-
console.log(chalk3.dim(`import { CommentProvider, CommentOverlay, CommentDrawer } from 'hale-commenting-system';
|
|
325
|
+
console.log(chalk3.dim(`import { CommentProvider, CommentOverlay, CommentDrawer, VersionProvider } from 'hale-commenting-system';
|
|
318
326
|
import { BrowserRouter as Router } from 'react-router-dom';
|
|
319
327
|
import React from 'react';
|
|
320
328
|
|
|
@@ -323,18 +331,20 @@ function App() {
|
|
|
323
331
|
|
|
324
332
|
return (
|
|
325
333
|
<Router>
|
|
326
|
-
<
|
|
327
|
-
<
|
|
328
|
-
|
|
329
|
-
onThreadSelect={setSelectedThreadId}
|
|
330
|
-
>
|
|
331
|
-
<CommentOverlay
|
|
334
|
+
<VersionProvider>
|
|
335
|
+
<CommentProvider>
|
|
336
|
+
<CommentDrawer
|
|
332
337
|
selectedThreadId={selectedThreadId}
|
|
333
338
|
onThreadSelect={setSelectedThreadId}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
339
|
+
>
|
|
340
|
+
<CommentOverlay
|
|
341
|
+
selectedThreadId={selectedThreadId}
|
|
342
|
+
onThreadSelect={setSelectedThreadId}
|
|
343
|
+
/>
|
|
344
|
+
{/* Your app content */}
|
|
345
|
+
</CommentDrawer>
|
|
346
|
+
</CommentProvider>
|
|
347
|
+
</VersionProvider>
|
|
338
348
|
</Router>
|
|
339
349
|
);
|
|
340
350
|
}
|
package/cli/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/commands/init.ts","../src/utils/detect.ts","../src/utils/logger.ts","../src/generators/code.ts","../src/utils/fs.ts"],"sourcesContent":["import { Command } from 'commander';\nimport chalk from 'chalk';\nimport { initCommand } from './commands/init.js';\n\nconst program = new Command();\n\nprogram\n .name('hale-commenting-system')\n .description('Hale Commenting System CLI - Local setup wizard')\n .version('2.0.0');\n\nprogram\n .command('init')\n .description('Initialize Hale Commenting System in your project')\n .option('-y, --yes', 'Skip prompts and use defaults')\n .action(async (options) => {\n try {\n await initCommand(options);\n } catch (error: any) {\n console.error(chalk.red('\\n✗ Error:'), error.message);\n process.exit(1);\n }\n });\n\n// Show help if no command provided\nif (!process.argv.slice(2).length) {\n program.help();\n}\n\nprogram.parse();\n","import chalk from 'chalk';\nimport ora from 'ora';\nimport inquirer from 'inquirer';\nimport { detectProject } from '../utils/detect.js';\nimport { printWelcome, printWarning } from '../utils/logger.js';\nimport { integrateProviders, showIntegrationDiff } from '../generators/code.js';\n\ninterface InitOptions {\n yes?: boolean;\n}\n\nexport async function initCommand(options: InitOptions) {\n printWelcome();\n\n const spinner = ora('Detecting project...').start();\n\n // Step 1: Detect project type\n let project;\n try {\n project = await detectProject(process.cwd());\n spinner.succeed(`Detected: ${project.framework} with ${project.buildTool}`);\n } catch (error: any) {\n spinner.fail(error.message);\n process.exit(1);\n }\n\n if (!project.isReact) {\n spinner.fail('This package requires a React project');\n console.log(chalk.red('\\n✗ Hale Commenting System requires React.\\n'));\n process.exit(1);\n }\n\n if (!project.hasPatternFly) {\n printWarning('PatternFly not detected. This package is optimized for PatternFly projects.');\n if (!options.yes) {\n const { continueAnyway } = await inquirer.prompt([\n {\n type: 'confirm',\n name: 'continueAnyway',\n message: 'Continue anyway?',\n default: false\n }\n ]);\n if (!continueAnyway) {\n console.log(chalk.dim('\\nSetup cancelled.\\n'));\n process.exit(0);\n }\n }\n }\n\n // Step 2: Auto-integrate providers\n console.log(chalk.cyan('\\n📦 Setting up local commenting system...\\n'));\n \n spinner.start('Integrating commenting system into your app...');\n const result = await integrateProviders(project.root);\n \n if (result.success) {\n spinner.succeed('Commenting system integrated!');\n showIntegrationDiff(result.filePath);\n console.log(chalk.green('\\n✓ Setup complete! Your app is ready to use the commenting system.\\n'));\n console.log(chalk.cyan('Next steps:'));\n console.log(chalk.white('1. Review the changes in your App file'));\n console.log(chalk.white('2. Start your dev server (e.g., npm run start:dev)'));\n console.log(chalk.white('3. Open your app in the browser'));\n console.log(chalk.white('4. Click anywhere to add comments (stored in localStorage)\\n'));\n console.log(chalk.dim('💡 Tip: Comments persist across page refreshes and are stored locally in your browser.\\n'));\n } else {\n spinner.warn(result.message);\n console.log(chalk.yellow('\\n⚠️ Could not automatically integrate the commenting system.\\n'));\n console.log(chalk.white('Please manually add the following to your App component:\\n'));\n console.log(chalk.dim(`import { CommentProvider, CommentOverlay, CommentDrawer } from 'hale-commenting-system';\nimport { BrowserRouter as Router } from 'react-router-dom';\nimport React from 'react';\n\nfunction App() {\n const [selectedThreadId, setSelectedThreadId] = React.useState<string | null>(null);\n\n return (\n <Router>\n <CommentProvider>\n <CommentDrawer \n selectedThreadId={selectedThreadId} \n onThreadSelect={setSelectedThreadId}\n >\n <CommentOverlay \n selectedThreadId={selectedThreadId} \n onThreadSelect={setSelectedThreadId}\n />\n {/* Your app content */}\n </CommentDrawer>\n </CommentProvider>\n </Router>\n );\n}\\n`));\n }\n}\n","import fs from 'fs/promises';\nimport path from 'path';\n\nexport interface ProjectInfo {\n root: string;\n framework: string;\n buildTool: string;\n isReact: boolean;\n hasPatternFly: boolean;\n hasTypeScript: boolean;\n packageJson: any;\n}\n\nexport async function detectProject(cwd: string): Promise<ProjectInfo> {\n const packageJsonPath = path.join(cwd, 'package.json');\n \n let packageJson: any = {};\n try {\n const content = await fs.readFile(packageJsonPath, 'utf-8');\n packageJson = JSON.parse(content);\n } catch (error) {\n throw new Error('No package.json found. Are you in a Node.js project?');\n }\n\n const deps = {\n ...packageJson.dependencies,\n ...packageJson.devDependencies\n };\n\n const buildTool = await detectBuildTool(cwd, deps);\n\n return {\n root: cwd,\n framework: detectFramework(deps),\n buildTool,\n isReact: !!deps['react'],\n hasPatternFly: !!deps['@patternfly/react-core'],\n hasTypeScript: !!deps['typescript'],\n packageJson\n };\n}\n\nfunction detectFramework(deps: any): string {\n if (deps['react']) return 'React';\n if (deps['vue']) return 'Vue';\n if (deps['@angular/core']) return 'Angular';\n return 'Unknown';\n}\n\nasync function detectBuildTool(cwd: string, deps: any): Promise<string> {\n if (deps['vite']) return 'Vite';\n if (deps['webpack']) return 'Webpack';\n \n try {\n await fs.access(path.join(cwd, 'next.config.js'));\n return 'Next.js';\n } catch {\n // Next.js config not found\n }\n\n return 'Unknown';\n}\n\nexport async function detectPlatform(cwd: string): Promise<string | null> {\n try {\n await fs.access(path.join(cwd, 'vercel.json'));\n return 'vercel';\n } catch {\n // Not Vercel\n }\n\n try {\n await fs.access(path.join(cwd, 'netlify.toml'));\n return 'netlify';\n } catch {\n // Not Netlify\n }\n\n return null;\n}\n\n","import chalk from 'chalk';\n\nexport function printWelcome() {\n console.log(chalk.bold.cyan('\\n🚀 Hale Commenting System - Local Setup\\n'));\n console.log(chalk.dim('Setting up a localStorage-based commenting system for your app.\\n'));\n}\n\nexport function printWarning(message: string) {\n console.log(chalk.yellow(`⚠️ ${message}`));\n}\n","import path from 'path';\nimport chalk from 'chalk';\nimport { readFile, writeFile, fileExists } from '../utils/fs.js';\n\ninterface IntegrationResult {\n success: boolean;\n filePath: string;\n message: string;\n}\n\nexport async function integrateProviders(projectRoot: string): Promise<IntegrationResult> {\n // Find the App entry point - try common locations\n const possiblePaths = [\n 'src/app/index.tsx',\n 'src/app/App.tsx',\n 'src/App.tsx',\n 'src/index.tsx'\n ];\n\n let appFilePath: string | null = null;\n \n for (const p of possiblePaths) {\n const fullPath = path.join(projectRoot, p);\n if (await fileExists(fullPath)) {\n appFilePath = fullPath;\n break;\n }\n }\n\n if (!appFilePath) {\n return {\n success: false,\n filePath: '',\n message: 'Could not find App entry point. Please integrate manually.'\n };\n }\n\n try {\n const content = await readFile(appFilePath);\n \n // Check if already integrated\n if (content.includes('hale-commenting-system') || content.includes('CommentProvider')) {\n return {\n success: false,\n filePath: appFilePath,\n message: 'Commenting system already integrated.'\n };\n }\n\n const modifiedContent = injectProviders(content);\n \n if (modifiedContent === content) {\n return {\n success: false,\n filePath: appFilePath,\n message: 'Could not automatically integrate. File structure not recognized.'\n };\n }\n\n await writeFile(appFilePath, modifiedContent);\n\n return {\n success: true,\n filePath: appFilePath,\n message: `Successfully integrated providers into ${path.relative(projectRoot, appFilePath)}`\n };\n } catch (error: any) {\n return {\n success: false,\n filePath: appFilePath,\n message: `Error: ${error.message}`\n };\n }\n}\n\nfunction injectProviders(content: string): string {\n // Add imports at the top (after existing imports)\n const imports = `import {\n CommentProvider,\n CommentOverlay,\n CommentDrawer\n} from 'hale-commenting-system';`;\n\n // Find the last import statement\n const importRegex = /import\\s+.*?from\\s+['\"].*?['\"];?/g;\n const matches = content.match(importRegex);\n \n if (!matches || matches.length === 0) {\n // No imports found, add at the beginning\n content = imports + '\\n\\n' + content;\n } else {\n const lastImport = matches[matches.length - 1];\n const lastImportIndex = content.lastIndexOf(lastImport);\n const insertPosition = lastImportIndex + lastImport.length;\n content = content.slice(0, insertPosition) + '\\n\\n' + imports + content.slice(insertPosition);\n }\n\n // Find the JSX in the component - handle both explicit return and implicit arrow return\n // Pattern 1: return ( <Router> or return <Router>\n // Pattern 2: => ( <Router> (implicit return)\n let returnMatch = content.match(/return\\s*\\(?[\\s\\n]*<(\\w+)/);\n let isImplicitReturn = false;\n \n if (!returnMatch) {\n // Try to match implicit arrow function return: => ( <Component>\n returnMatch = content.match(/=>\\s*\\(?[\\s\\n]*<(\\w+)/);\n isImplicitReturn = true;\n }\n \n if (!returnMatch) {\n return content; // Can't find return statement or JSX\n }\n\n const componentName = returnMatch[1]; // Router, Fragment, etc.\n \n // Find the closing tag\n const closingTag = `</${componentName}>`;\n const closingIndex = content.indexOf(closingTag);\n \n if (closingIndex === -1) {\n return content; // Can't find closing tag\n }\n\n // Convert implicit return to explicit return if needed\n if (isImplicitReturn) {\n // Find the arrow function: const App = () => (\n const arrowMatch = content.match(/(const\\s+\\w+.*?=.*?\\(\\).*?=>\\s*)\\(/);\n if (arrowMatch) {\n const beforeParen = arrowMatch[1];\n const arrowEndPos = arrowMatch.index! + arrowMatch[0].length - 1; // Position before the (\n \n // Find the closing paren + semicolon\n const closingParenPos = content.indexOf(');', closingIndex);\n if (closingParenPos !== -1) {\n // Convert: const App = () => (...) to const App = () => { return (...) }\n const jsxContent = content.slice(arrowEndPos + 1, closingParenPos);\n content = content.slice(0, arrowEndPos) + ' {\\n return' + jsxContent + '\\n}' + content.slice(closingParenPos + 2);\n }\n }\n }\n\n // Add state hook before return\n const stateHook = ` const [selectedThreadId, setSelectedThreadId] = React.useState<string | null>(null);\\n\\n`;\n \n // Find the function body (after function declaration) - now guaranteed to have braces\n const functionMatch = content.match(/const\\s+\\w+.*?=.*?\\(\\).*?=>\\s*\\{/);\n if (functionMatch) {\n const insertPos = functionMatch.index! + functionMatch[0].length;\n content = content.slice(0, insertPos) + '\\n' + stateHook + content.slice(insertPos);\n }\n\n // Wrap the return content with providers\n const returnStartMatch = content.match(/return\\s*\\(?[\\s\\n]*</);\n if (returnStartMatch) {\n const returnStart = returnStartMatch.index! + returnStartMatch[0].length - 1; // Position before <\n const returnEnd = content.indexOf(closingTag, returnStart) + closingTag.length;\n \n const originalReturn = content.slice(returnStart, returnEnd).trim();\n \n // Check if the original return starts with <Router> or <BrowserRouter>\n const isRouter = originalReturn.match(/^\\s*<(Router|BrowserRouter)/);\n \n let wrappedReturn;\n if (isRouter) {\n // Extract Router content - need to find the inner content\n const routerMatch = originalReturn.match(/<(Router|BrowserRouter)[^>]*>([\\s\\S]*)<\\/\\1>/);\n if (routerMatch) {\n const routerType = routerMatch[1];\n const innerContent = routerMatch[2];\n \n // Put Router on outside, CommentProvider inside\n wrappedReturn = `\n <${routerType}>\n <CommentProvider>\n <CommentDrawer \n selectedThreadId={selectedThreadId} \n onThreadSelect={setSelectedThreadId}\n >\n <CommentOverlay \n selectedThreadId={selectedThreadId} \n onThreadSelect={setSelectedThreadId}\n />\n ${innerContent.trim()}\n </CommentDrawer>\n </CommentProvider>\n </${routerType}>\n `;\n } else {\n // Fallback to wrapping everything\n wrappedReturn = `\n <CommentProvider>\n <CommentDrawer \n selectedThreadId={selectedThreadId} \n onThreadSelect={setSelectedThreadId}\n >\n <CommentOverlay \n selectedThreadId={selectedThreadId} \n onThreadSelect={setSelectedThreadId}\n />\n ${originalReturn}\n </CommentDrawer>\n </CommentProvider>\n `;\n }\n } else {\n // No router, wrap everything normally\n wrappedReturn = `\n <CommentProvider>\n <CommentDrawer \n selectedThreadId={selectedThreadId} \n onThreadSelect={setSelectedThreadId}\n >\n <CommentOverlay \n selectedThreadId={selectedThreadId} \n onThreadSelect={setSelectedThreadId}\n />\n ${originalReturn}\n </CommentDrawer>\n </CommentProvider>\n `;\n }\n \n content = content.slice(0, returnStart) + wrappedReturn + content.slice(returnEnd);\n }\n\n return content;\n}\n\nexport function showIntegrationDiff(filePath: string) {\n console.log(chalk.cyan('\\nChanges made to your App file:'));\n console.log(chalk.white('• Added commenting system imports'));\n console.log(chalk.white('• Added state hook for comment thread selection'));\n console.log(chalk.white('• Wrapped app with CommentProvider'));\n console.log(chalk.white('• Added CommentDrawer and CommentOverlay components\\n'));\n console.log(chalk.dim(`Modified: ${filePath}\\n`));\n}\n","import fs from 'fs/promises';\nimport path from 'path';\n\nexport async function fileExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function ensureDir(dirPath: string): Promise<void> {\n await fs.mkdir(dirPath, { recursive: true });\n}\n\nexport async function writeFileIfNotExists(filePath: string, content: string): Promise<boolean> {\n const exists = await fileExists(filePath);\n if (exists) {\n return false;\n }\n \n await fs.writeFile(filePath, content, 'utf-8');\n return true;\n}\n\nexport async function appendToFile(filePath: string, content: string): Promise<void> {\n await fs.appendFile(filePath, content, 'utf-8');\n}\n\nexport async function readFile(filePath: string): Promise<string> {\n return fs.readFile(filePath, 'utf-8');\n}\n\nexport async function writeFile(filePath: string, content: string): Promise<void> {\n await fs.writeFile(filePath, content, 'utf-8');\n}\n\nexport function getRelativePath(from: string, to: string): string {\n return path.relative(from, to);\n}\n\n"],"mappings":";;;AAAA,SAAS,eAAe;AACxB,OAAOA,YAAW;;;ACDlB,OAAOC,YAAW;AAClB,OAAO,SAAS;AAChB,OAAO,cAAc;;;ACFrB,OAAO,QAAQ;AACf,OAAO,UAAU;AAYjB,eAAsB,cAAc,KAAmC;AACrE,QAAM,kBAAkB,KAAK,KAAK,KAAK,cAAc;AAErD,MAAI,cAAmB,CAAC;AACxB,MAAI;AACF,UAAM,UAAU,MAAM,GAAG,SAAS,iBAAiB,OAAO;AAC1D,kBAAc,KAAK,MAAM,OAAO;AAAA,EAClC,SAAS,OAAO;AACd,UAAM,IAAI,MAAM,sDAAsD;AAAA,EACxE;AAEA,QAAM,OAAO;AAAA,IACX,GAAG,YAAY;AAAA,IACf,GAAG,YAAY;AAAA,EACjB;AAEA,QAAM,YAAY,MAAM,gBAAgB,KAAK,IAAI;AAEjD,SAAO;AAAA,IACL,MAAM;AAAA,IACN,WAAW,gBAAgB,IAAI;AAAA,IAC/B;AAAA,IACA,SAAS,CAAC,CAAC,KAAK,OAAO;AAAA,IACvB,eAAe,CAAC,CAAC,KAAK,wBAAwB;AAAA,IAC9C,eAAe,CAAC,CAAC,KAAK,YAAY;AAAA,IAClC;AAAA,EACF;AACF;AAEA,SAAS,gBAAgB,MAAmB;AAC1C,MAAI,KAAK,OAAO,EAAG,QAAO;AAC1B,MAAI,KAAK,KAAK,EAAG,QAAO;AACxB,MAAI,KAAK,eAAe,EAAG,QAAO;AAClC,SAAO;AACT;AAEA,eAAe,gBAAgB,KAAa,MAA4B;AACtE,MAAI,KAAK,MAAM,EAAG,QAAO;AACzB,MAAI,KAAK,SAAS,EAAG,QAAO;AAE5B,MAAI;AACF,UAAM,GAAG,OAAO,KAAK,KAAK,KAAK,gBAAgB,CAAC;AAChD,WAAO;AAAA,EACT,QAAQ;AAAA,EAER;AAEA,SAAO;AACT;;;AC7DA,OAAO,WAAW;AAEX,SAAS,eAAe;AAC7B,UAAQ,IAAI,MAAM,KAAK,KAAK,oDAA6C,CAAC;AAC1E,UAAQ,IAAI,MAAM,IAAI,mEAAmE,CAAC;AAC5F;AAEO,SAAS,aAAa,SAAiB;AAC5C,UAAQ,IAAI,MAAM,OAAO,iBAAO,OAAO,EAAE,CAAC;AAC5C;;;ACTA,OAAOC,WAAU;AACjB,OAAOC,YAAW;;;ACDlB,OAAOC,SAAQ;AAGf,eAAsB,WAAW,UAAoC;AACnE,MAAI;AACF,UAAMC,IAAG,OAAO,QAAQ;AACxB,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAoBA,eAAsB,SAAS,UAAmC;AAChE,SAAOC,IAAG,SAAS,UAAU,OAAO;AACtC;AAEA,eAAsB,UAAU,UAAkB,SAAgC;AAChF,QAAMA,IAAG,UAAU,UAAU,SAAS,OAAO;AAC/C;;;AD1BA,eAAsB,mBAAmB,aAAiD;AAExF,QAAM,gBAAgB;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,MAAI,cAA6B;AAEjC,aAAW,KAAK,eAAe;AAC7B,UAAM,WAAWC,MAAK,KAAK,aAAa,CAAC;AACzC,QAAI,MAAM,WAAW,QAAQ,GAAG;AAC9B,oBAAc;AACd;AAAA,IACF;AAAA,EACF;AAEA,MAAI,CAAC,aAAa;AAChB,WAAO;AAAA,MACL,SAAS;AAAA,MACT,UAAU;AAAA,MACV,SAAS;AAAA,IACX;AAAA,EACF;AAEA,MAAI;AACF,UAAM,UAAU,MAAM,SAAS,WAAW;AAG1C,QAAI,QAAQ,SAAS,wBAAwB,KAAK,QAAQ,SAAS,iBAAiB,GAAG;AACrF,aAAO;AAAA,QACL,SAAS;AAAA,QACT,UAAU;AAAA,QACV,SAAS;AAAA,MACX;AAAA,IACF;AAEA,UAAM,kBAAkB,gBAAgB,OAAO;AAE/C,QAAI,oBAAoB,SAAS;AAC/B,aAAO;AAAA,QACL,SAAS;AAAA,QACT,UAAU;AAAA,QACV,SAAS;AAAA,MACX;AAAA,IACF;AAEA,UAAM,UAAU,aAAa,eAAe;AAE5C,WAAO;AAAA,MACL,SAAS;AAAA,MACT,UAAU;AAAA,MACV,SAAS,0CAA0CA,MAAK,SAAS,aAAa,WAAW,CAAC;AAAA,IAC5F;AAAA,EACF,SAAS,OAAY;AACnB,WAAO;AAAA,MACL,SAAS;AAAA,MACT,UAAU;AAAA,MACV,SAAS,UAAU,MAAM,OAAO;AAAA,IAClC;AAAA,EACF;AACF;AAEA,SAAS,gBAAgB,SAAyB;AAEhD,QAAM,UAAU;AAAA;AAAA;AAAA;AAAA;AAOhB,QAAM,cAAc;AACpB,QAAM,UAAU,QAAQ,MAAM,WAAW;AAEzC,MAAI,CAAC,WAAW,QAAQ,WAAW,GAAG;AAEpC,cAAU,UAAU,SAAS;AAAA,EAC/B,OAAO;AACL,UAAM,aAAa,QAAQ,QAAQ,SAAS,CAAC;AAC7C,UAAM,kBAAkB,QAAQ,YAAY,UAAU;AACtD,UAAM,iBAAiB,kBAAkB,WAAW;AACpD,cAAU,QAAQ,MAAM,GAAG,cAAc,IAAI,SAAS,UAAU,QAAQ,MAAM,cAAc;AAAA,EAC9F;AAKA,MAAI,cAAc,QAAQ,MAAM,2BAA2B;AAC3D,MAAI,mBAAmB;AAEvB,MAAI,CAAC,aAAa;AAEhB,kBAAc,QAAQ,MAAM,uBAAuB;AACnD,uBAAmB;AAAA,EACrB;AAEA,MAAI,CAAC,aAAa;AAChB,WAAO;AAAA,EACT;AAEA,QAAM,gBAAgB,YAAY,CAAC;AAGnC,QAAM,aAAa,KAAK,aAAa;AACrC,QAAM,eAAe,QAAQ,QAAQ,UAAU;AAE/C,MAAI,iBAAiB,IAAI;AACvB,WAAO;AAAA,EACT;AAGA,MAAI,kBAAkB;AAEpB,UAAM,aAAa,QAAQ,MAAM,oCAAoC;AACrE,QAAI,YAAY;AACd,YAAM,cAAc,WAAW,CAAC;AAChC,YAAM,cAAc,WAAW,QAAS,WAAW,CAAC,EAAE,SAAS;AAG/D,YAAM,kBAAkB,QAAQ,QAAQ,MAAM,YAAY;AAC1D,UAAI,oBAAoB,IAAI;AAE1B,cAAM,aAAa,QAAQ,MAAM,cAAc,GAAG,eAAe;AACjE,kBAAU,QAAQ,MAAM,GAAG,WAAW,IAAI,iBAAiB,aAAa,QAAQ,QAAQ,MAAM,kBAAkB,CAAC;AAAA,MACnH;AAAA,IACF;AAAA,EACF;AAGA,QAAM,YAAY;AAAA;AAAA;AAGlB,QAAM,gBAAgB,QAAQ,MAAM,kCAAkC;AACtE,MAAI,eAAe;AACjB,UAAM,YAAY,cAAc,QAAS,cAAc,CAAC,EAAE;AAC1D,cAAU,QAAQ,MAAM,GAAG,SAAS,IAAI,OAAO,YAAY,QAAQ,MAAM,SAAS;AAAA,EACpF;AAGA,QAAM,mBAAmB,QAAQ,MAAM,sBAAsB;AAC7D,MAAI,kBAAkB;AACpB,UAAM,cAAc,iBAAiB,QAAS,iBAAiB,CAAC,EAAE,SAAS;AAC3E,UAAM,YAAY,QAAQ,QAAQ,YAAY,WAAW,IAAI,WAAW;AAExE,UAAM,iBAAiB,QAAQ,MAAM,aAAa,SAAS,EAAE,KAAK;AAGlE,UAAM,WAAW,eAAe,MAAM,6BAA6B;AAEnE,QAAI;AACJ,QAAI,UAAU;AAEZ,YAAM,cAAc,eAAe,MAAM,8CAA8C;AACvF,UAAI,aAAa;AACf,cAAM,aAAa,YAAY,CAAC;AAChC,cAAM,eAAe,YAAY,CAAC;AAGlC,wBAAgB;AAAA,OACjB,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAUL,aAAa,KAAK,CAAC;AAAA;AAAA;AAAA,QAGvB,UAAU;AAAA;AAAA,MAEZ,OAAO;AAEL,wBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAUd,cAAc;AAAA;AAAA;AAAA;AAAA,MAIlB;AAAA,IACF,OAAO;AAEL,sBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAUZ,cAAc;AAAA;AAAA;AAAA;AAAA,IAIpB;AAEA,cAAU,QAAQ,MAAM,GAAG,WAAW,IAAI,gBAAgB,QAAQ,MAAM,SAAS;AAAA,EACnF;AAEA,SAAO;AACT;AAEO,SAAS,oBAAoB,UAAkB;AACpD,UAAQ,IAAIC,OAAM,KAAK,kCAAkC,CAAC;AAC1D,UAAQ,IAAIA,OAAM,MAAM,wCAAmC,CAAC;AAC5D,UAAQ,IAAIA,OAAM,MAAM,sDAAiD,CAAC;AAC1E,UAAQ,IAAIA,OAAM,MAAM,yCAAoC,CAAC;AAC7D,UAAQ,IAAIA,OAAM,MAAM,4DAAuD,CAAC;AAChF,UAAQ,IAAIA,OAAM,IAAI,aAAa,QAAQ;AAAA,CAAI,CAAC;AAClD;;;AHhOA,eAAsB,YAAY,SAAsB;AACtD,eAAa;AAEb,QAAM,UAAU,IAAI,sBAAsB,EAAE,MAAM;AAGlD,MAAI;AACJ,MAAI;AACF,cAAU,MAAM,cAAc,QAAQ,IAAI,CAAC;AAC3C,YAAQ,QAAQ,aAAa,QAAQ,SAAS,SAAS,QAAQ,SAAS,EAAE;AAAA,EAC5E,SAAS,OAAY;AACnB,YAAQ,KAAK,MAAM,OAAO;AAC1B,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI,CAAC,QAAQ,SAAS;AACpB,YAAQ,KAAK,uCAAuC;AACpD,YAAQ,IAAIC,OAAM,IAAI,mDAA8C,CAAC;AACrE,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI,CAAC,QAAQ,eAAe;AAC1B,iBAAa,6EAA6E;AAC1F,QAAI,CAAC,QAAQ,KAAK;AAChB,YAAM,EAAE,eAAe,IAAI,MAAM,SAAS,OAAO;AAAA,QAC/C;AAAA,UACE,MAAM;AAAA,UACN,MAAM;AAAA,UACN,SAAS;AAAA,UACT,SAAS;AAAA,QACX;AAAA,MACF,CAAC;AACD,UAAI,CAAC,gBAAgB;AACnB,gBAAQ,IAAIA,OAAM,IAAI,sBAAsB,CAAC;AAC7C,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AAGA,UAAQ,IAAIA,OAAM,KAAK,qDAA8C,CAAC;AAEtE,UAAQ,MAAM,gDAAgD;AAC9D,QAAM,SAAS,MAAM,mBAAmB,QAAQ,IAAI;AAEpD,MAAI,OAAO,SAAS;AAClB,YAAQ,QAAQ,+BAA+B;AAC/C,wBAAoB,OAAO,QAAQ;AACnC,YAAQ,IAAIA,OAAM,MAAM,4EAAuE,CAAC;AAChG,YAAQ,IAAIA,OAAM,KAAK,aAAa,CAAC;AACrC,YAAQ,IAAIA,OAAM,MAAM,wCAAwC,CAAC;AACjE,YAAQ,IAAIA,OAAM,MAAM,oDAAoD,CAAC;AAC7E,YAAQ,IAAIA,OAAM,MAAM,iCAAiC,CAAC;AAC1D,YAAQ,IAAIA,OAAM,MAAM,8DAA8D,CAAC;AACvF,YAAQ,IAAIA,OAAM,IAAI,iGAA0F,CAAC;AAAA,EACnH,OAAO;AACL,YAAQ,KAAK,OAAO,OAAO;AAC3B,YAAQ,IAAIA,OAAM,OAAO,4EAAkE,CAAC;AAC5F,YAAQ,IAAIA,OAAM,MAAM,4DAA4D,CAAC;AACrF,YAAQ,IAAIA,OAAM,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAuBtB,CAAC;AAAA,EACH;AACF;;;AD3FA,IAAM,UAAU,IAAI,QAAQ;AAE5B,QACG,KAAK,wBAAwB,EAC7B,YAAY,iDAAiD,EAC7D,QAAQ,OAAO;AAElB,QACG,QAAQ,MAAM,EACd,YAAY,mDAAmD,EAC/D,OAAO,aAAa,+BAA+B,EACnD,OAAO,OAAO,YAAY;AACzB,MAAI;AACF,UAAM,YAAY,OAAO;AAAA,EAC3B,SAAS,OAAY;AACnB,YAAQ,MAAMC,OAAM,IAAI,iBAAY,GAAG,MAAM,OAAO;AACpD,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;AAGH,IAAI,CAAC,QAAQ,KAAK,MAAM,CAAC,EAAE,QAAQ;AACjC,UAAQ,KAAK;AACf;AAEA,QAAQ,MAAM;","names":["chalk","chalk","path","chalk","fs","fs","fs","path","chalk","chalk","chalk"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/commands/init.ts","../src/utils/detect.ts","../src/utils/logger.ts","../src/generators/code.ts","../src/utils/fs.ts"],"sourcesContent":["import { Command } from 'commander';\nimport chalk from 'chalk';\nimport { initCommand } from './commands/init.js';\n\nconst program = new Command();\n\nprogram\n .name('hale-commenting-system')\n .description('Hale Commenting System CLI - Local setup wizard')\n .version('2.0.0');\n\nprogram\n .command('init')\n .description('Initialize Hale Commenting System in your project')\n .option('-y, --yes', 'Skip prompts and use defaults')\n .action(async (options) => {\n try {\n await initCommand(options);\n } catch (error: any) {\n console.error(chalk.red('\\n✗ Error:'), error.message);\n process.exit(1);\n }\n });\n\n// Show help if no command provided\nif (!process.argv.slice(2).length) {\n program.help();\n}\n\nprogram.parse();\n","import chalk from 'chalk';\nimport ora from 'ora';\nimport inquirer from 'inquirer';\nimport { detectProject } from '../utils/detect.js';\nimport { printWelcome, printWarning } from '../utils/logger.js';\nimport { integrateProviders, showIntegrationDiff } from '../generators/code.js';\n\ninterface InitOptions {\n yes?: boolean;\n}\n\nexport async function initCommand(options: InitOptions) {\n printWelcome();\n\n const spinner = ora('Detecting project...').start();\n\n // Step 1: Detect project type\n let project;\n try {\n project = await detectProject(process.cwd());\n spinner.succeed(`Detected: ${project.framework} with ${project.buildTool}`);\n } catch (error: any) {\n spinner.fail(error.message);\n process.exit(1);\n }\n\n if (!project.isReact) {\n spinner.fail('This package requires a React project');\n console.log(chalk.red('\\n✗ Hale Commenting System requires React.\\n'));\n process.exit(1);\n }\n\n if (!project.hasPatternFly) {\n printWarning('PatternFly not detected. This package is optimized for PatternFly projects.');\n if (!options.yes) {\n const { continueAnyway } = await inquirer.prompt([\n {\n type: 'confirm',\n name: 'continueAnyway',\n message: 'Continue anyway?',\n default: false\n }\n ]);\n if (!continueAnyway) {\n console.log(chalk.dim('\\nSetup cancelled.\\n'));\n process.exit(0);\n }\n }\n }\n\n // Step 2: Auto-integrate providers\n console.log(chalk.cyan('\\n📦 Setting up local commenting system...\\n'));\n \n spinner.start('Integrating commenting system into your app...');\n const result = await integrateProviders(project.root);\n \n if (result.success) {\n spinner.succeed('Commenting system integrated!');\n showIntegrationDiff(result.filePath);\n console.log(chalk.green('\\n✓ Setup complete! Your app is ready to use the commenting system.\\n'));\n console.log(chalk.cyan('Next steps:'));\n console.log(chalk.white('1. Review the changes in your App file'));\n console.log(chalk.white('2. Start your dev server (e.g., npm run start:dev)'));\n console.log(chalk.white('3. Open your app in the browser'));\n console.log(chalk.white('4. Click anywhere to add comments (stored in localStorage)\\n'));\n console.log(chalk.dim('💡 Tip: Comments persist across page refreshes and are stored locally in your browser.\\n'));\n } else {\n spinner.warn(result.message);\n console.log(chalk.yellow('\\n⚠️ Could not automatically integrate the commenting system.\\n'));\n console.log(chalk.white('Please manually add the following to your App component:\\n'));\n console.log(chalk.dim(`import { CommentProvider, CommentOverlay, CommentDrawer, VersionProvider } from 'hale-commenting-system';\nimport { BrowserRouter as Router } from 'react-router-dom';\nimport React from 'react';\n\nfunction App() {\n const [selectedThreadId, setSelectedThreadId] = React.useState<string | null>(null);\n\n return (\n <Router>\n <VersionProvider>\n <CommentProvider>\n <CommentDrawer \n selectedThreadId={selectedThreadId} \n onThreadSelect={setSelectedThreadId}\n >\n <CommentOverlay \n selectedThreadId={selectedThreadId} \n onThreadSelect={setSelectedThreadId}\n />\n {/* Your app content */}\n </CommentDrawer>\n </CommentProvider>\n </VersionProvider>\n </Router>\n );\n}\\n`));\n }\n}\n","import fs from 'fs/promises';\nimport path from 'path';\n\nexport interface ProjectInfo {\n root: string;\n framework: string;\n buildTool: string;\n isReact: boolean;\n hasPatternFly: boolean;\n hasTypeScript: boolean;\n packageJson: any;\n}\n\nexport async function detectProject(cwd: string): Promise<ProjectInfo> {\n const packageJsonPath = path.join(cwd, 'package.json');\n \n let packageJson: any = {};\n try {\n const content = await fs.readFile(packageJsonPath, 'utf-8');\n packageJson = JSON.parse(content);\n } catch (error) {\n throw new Error('No package.json found. Are you in a Node.js project?');\n }\n\n const deps = {\n ...packageJson.dependencies,\n ...packageJson.devDependencies\n };\n\n const buildTool = await detectBuildTool(cwd, deps);\n\n return {\n root: cwd,\n framework: detectFramework(deps),\n buildTool,\n isReact: !!deps['react'],\n hasPatternFly: !!deps['@patternfly/react-core'],\n hasTypeScript: !!deps['typescript'],\n packageJson\n };\n}\n\nfunction detectFramework(deps: any): string {\n if (deps['react']) return 'React';\n if (deps['vue']) return 'Vue';\n if (deps['@angular/core']) return 'Angular';\n return 'Unknown';\n}\n\nasync function detectBuildTool(cwd: string, deps: any): Promise<string> {\n if (deps['vite']) return 'Vite';\n if (deps['webpack']) return 'Webpack';\n \n try {\n await fs.access(path.join(cwd, 'next.config.js'));\n return 'Next.js';\n } catch {\n // Next.js config not found\n }\n\n return 'Unknown';\n}\n\nexport async function detectPlatform(cwd: string): Promise<string | null> {\n try {\n await fs.access(path.join(cwd, 'vercel.json'));\n return 'vercel';\n } catch {\n // Not Vercel\n }\n\n try {\n await fs.access(path.join(cwd, 'netlify.toml'));\n return 'netlify';\n } catch {\n // Not Netlify\n }\n\n return null;\n}\n\n","import chalk from 'chalk';\n\nexport function printWelcome() {\n console.log(chalk.bold.cyan('\\n🚀 Hale Commenting System - Local Setup\\n'));\n console.log(chalk.dim('Setting up a localStorage-based commenting system for your app.\\n'));\n}\n\nexport function printWarning(message: string) {\n console.log(chalk.yellow(`⚠️ ${message}`));\n}\n","import path from 'path';\nimport chalk from 'chalk';\nimport { readFile, writeFile, fileExists } from '../utils/fs.js';\n\ninterface IntegrationResult {\n success: boolean;\n filePath: string;\n message: string;\n}\n\nexport async function integrateProviders(projectRoot: string): Promise<IntegrationResult> {\n // Find the App entry point - try common locations\n const possiblePaths = [\n 'src/app/index.tsx',\n 'src/app/App.tsx',\n 'src/App.tsx',\n 'src/index.tsx'\n ];\n\n let appFilePath: string | null = null;\n \n for (const p of possiblePaths) {\n const fullPath = path.join(projectRoot, p);\n if (await fileExists(fullPath)) {\n appFilePath = fullPath;\n break;\n }\n }\n\n if (!appFilePath) {\n return {\n success: false,\n filePath: '',\n message: 'Could not find App entry point. Please integrate manually.'\n };\n }\n\n try {\n const content = await readFile(appFilePath);\n \n // Check if already integrated\n if (content.includes('hale-commenting-system') || content.includes('CommentProvider')) {\n return {\n success: false,\n filePath: appFilePath,\n message: 'Commenting system already integrated.'\n };\n }\n\n const modifiedContent = injectProviders(content);\n \n if (modifiedContent === content) {\n return {\n success: false,\n filePath: appFilePath,\n message: 'Could not automatically integrate. File structure not recognized.'\n };\n }\n\n await writeFile(appFilePath, modifiedContent);\n\n return {\n success: true,\n filePath: appFilePath,\n message: `Successfully integrated providers into ${path.relative(projectRoot, appFilePath)}`\n };\n } catch (error: any) {\n return {\n success: false,\n filePath: appFilePath,\n message: `Error: ${error.message}`\n };\n }\n}\n\nfunction injectProviders(content: string): string {\n // Add imports at the top (after existing imports)\n const imports = `import {\n CommentProvider,\n CommentOverlay,\n CommentDrawer,\n useComments,\n VersionProvider\n} from 'hale-commenting-system';`;\n\n // Find the last import statement\n const importRegex = /import\\s+.*?from\\s+['\"].*?['\"];?/g;\n const matches = content.match(importRegex);\n \n if (!matches || matches.length === 0) {\n // No imports found, add at the beginning\n content = imports + '\\n\\n' + content;\n } else {\n const lastImport = matches[matches.length - 1];\n const lastImportIndex = content.lastIndexOf(lastImport);\n const insertPosition = lastImportIndex + lastImport.length;\n content = content.slice(0, insertPosition) + '\\n\\n' + imports + content.slice(insertPosition);\n }\n\n // Find the JSX in the component - handle both explicit return and implicit arrow return\n // Pattern 1: return ( <Router> or return <Router>\n // Pattern 2: => ( <Router> (implicit return)\n let returnMatch = content.match(/return\\s*\\(?[\\s\\n]*<(\\w+)/);\n let isImplicitReturn = false;\n \n if (!returnMatch) {\n // Try to match implicit arrow function return: => ( <Component>\n returnMatch = content.match(/=>\\s*\\(?[\\s\\n]*<(\\w+)/);\n isImplicitReturn = true;\n }\n \n if (!returnMatch) {\n return content; // Can't find return statement or JSX\n }\n\n const componentName = returnMatch[1]; // Router, Fragment, etc.\n \n // Find the closing tag\n const closingTag = `</${componentName}>`;\n const closingIndex = content.indexOf(closingTag);\n \n if (closingIndex === -1) {\n return content; // Can't find closing tag\n }\n\n // Convert implicit return to explicit return if needed\n if (isImplicitReturn) {\n // Find the arrow function: const App = () => (\n const arrowMatch = content.match(/(const\\s+\\w+.*?=.*?\\(\\).*?=>\\s*)\\(/);\n if (arrowMatch) {\n const beforeParen = arrowMatch[1];\n const arrowEndPos = arrowMatch.index! + arrowMatch[0].length - 1; // Position before the (\n \n // Find the closing paren + semicolon\n const closingParenPos = content.indexOf(');', closingIndex);\n if (closingParenPos !== -1) {\n // Convert: const App = () => (...) to const App = () => { return (...) }\n const jsxContent = content.slice(arrowEndPos + 1, closingParenPos);\n content = content.slice(0, arrowEndPos) + ' {\\n return' + jsxContent + '\\n}' + content.slice(closingParenPos + 2);\n }\n }\n }\n\n // Add state hook before return\n const stateHook = ` const [selectedThreadId, setSelectedThreadId] = React.useState<string | null>(null);\\n\\n`;\n \n // Find the function body (after function declaration) - now guaranteed to have braces\n const functionMatch = content.match(/const\\s+\\w+.*?=.*?\\(\\).*?=>\\s*\\{/);\n if (functionMatch) {\n const insertPos = functionMatch.index! + functionMatch[0].length;\n content = content.slice(0, insertPos) + '\\n' + stateHook + content.slice(insertPos);\n }\n\n // Wrap the return content with providers\n const returnStartMatch = content.match(/return\\s*\\(?[\\s\\n]*</);\n if (returnStartMatch) {\n const returnStart = returnStartMatch.index! + returnStartMatch[0].length - 1; // Position before <\n const returnEnd = content.indexOf(closingTag, returnStart) + closingTag.length;\n \n const originalReturn = content.slice(returnStart, returnEnd).trim();\n \n // Check if the original return starts with <Router> or <BrowserRouter>\n const isRouter = originalReturn.match(/^\\s*<(Router|BrowserRouter)/);\n \n let wrappedReturn;\n if (isRouter) {\n // Extract Router content - need to find the inner content\n const routerMatch = originalReturn.match(/<(Router|BrowserRouter)[^>]*>([\\s\\S]*)<\\/\\1>/);\n if (routerMatch) {\n const routerType = routerMatch[1];\n const innerContent = routerMatch[2];\n \n // Put Router on outside, VersionProvider and CommentProvider inside\n wrappedReturn = `\n <${routerType}>\n <VersionProvider>\n <CommentProvider>\n <CommentDrawer \n selectedThreadId={selectedThreadId} \n onThreadSelect={setSelectedThreadId}\n >\n <CommentOverlay \n selectedThreadId={selectedThreadId} \n onThreadSelect={setSelectedThreadId}\n />\n ${innerContent.trim()}\n </CommentDrawer>\n </CommentProvider>\n </VersionProvider>\n </${routerType}>\n `;\n } else {\n // Fallback to wrapping everything\n wrappedReturn = `\n <VersionProvider>\n <CommentProvider>\n <CommentDrawer \n selectedThreadId={selectedThreadId} \n onThreadSelect={setSelectedThreadId}\n >\n <CommentOverlay \n selectedThreadId={selectedThreadId} \n onThreadSelect={setSelectedThreadId}\n />\n ${originalReturn}\n </CommentDrawer>\n </CommentProvider>\n </VersionProvider>\n `;\n }\n } else {\n // No router, wrap everything normally\n wrappedReturn = `\n <VersionProvider>\n <CommentProvider>\n <CommentDrawer \n selectedThreadId={selectedThreadId} \n onThreadSelect={setSelectedThreadId}\n >\n <CommentOverlay \n selectedThreadId={selectedThreadId} \n onThreadSelect={setSelectedThreadId}\n />\n ${originalReturn}\n </CommentDrawer>\n </CommentProvider>\n </VersionProvider>\n `;\n }\n \n content = content.slice(0, returnStart) + wrappedReturn + content.slice(returnEnd);\n }\n\n return content;\n}\n\nexport function showIntegrationDiff(filePath: string) {\n console.log(chalk.cyan('\\nChanges made to your App file:'));\n console.log(chalk.white('• Added commenting system imports'));\n console.log(chalk.white('• Added state hook for comment thread selection'));\n console.log(chalk.white('• Wrapped app with CommentProvider'));\n console.log(chalk.white('• Added CommentDrawer and CommentOverlay components\\n'));\n console.log(chalk.dim(`Modified: ${filePath}\\n`));\n}\n","import fs from 'fs/promises';\nimport path from 'path';\n\nexport async function fileExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function ensureDir(dirPath: string): Promise<void> {\n await fs.mkdir(dirPath, { recursive: true });\n}\n\nexport async function writeFileIfNotExists(filePath: string, content: string): Promise<boolean> {\n const exists = await fileExists(filePath);\n if (exists) {\n return false;\n }\n \n await fs.writeFile(filePath, content, 'utf-8');\n return true;\n}\n\nexport async function appendToFile(filePath: string, content: string): Promise<void> {\n await fs.appendFile(filePath, content, 'utf-8');\n}\n\nexport async function readFile(filePath: string): Promise<string> {\n return fs.readFile(filePath, 'utf-8');\n}\n\nexport async function writeFile(filePath: string, content: string): Promise<void> {\n await fs.writeFile(filePath, content, 'utf-8');\n}\n\nexport function getRelativePath(from: string, to: string): string {\n return path.relative(from, to);\n}\n\n"],"mappings":"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","names":["chalk","chalk","path","chalk","fs","fs","fs","path","chalk","chalk","chalk"]}
|
package/package.json
CHANGED