@feardread/fear 1.0.1

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.
Files changed (99) hide show
  1. package/FEAR.js +459 -0
  2. package/FEARServer.js +280 -0
  3. package/controllers/agent.js +438 -0
  4. package/controllers/auth/index.js +345 -0
  5. package/controllers/auth/token.js +50 -0
  6. package/controllers/blog.js +105 -0
  7. package/controllers/brand.js +10 -0
  8. package/controllers/cart.js +425 -0
  9. package/controllers/category.js +9 -0
  10. package/controllers/coupon.js +63 -0
  11. package/controllers/crud/crud.js +508 -0
  12. package/controllers/crud/index.js +36 -0
  13. package/controllers/email.js +34 -0
  14. package/controllers/enquiry.js +65 -0
  15. package/controllers/events.js +9 -0
  16. package/controllers/order.js +125 -0
  17. package/controllers/payment.js +31 -0
  18. package/controllers/product.js +147 -0
  19. package/controllers/review.js +247 -0
  20. package/controllers/tag.js +10 -0
  21. package/controllers/task.js +10 -0
  22. package/controllers/upload.js +41 -0
  23. package/controllers/user.js +401 -0
  24. package/index.js +7 -0
  25. package/libs/agent/index.js +561 -0
  26. package/libs/agent/modules/ai/ai.js +285 -0
  27. package/libs/agent/modules/ai/chat.js +518 -0
  28. package/libs/agent/modules/ai/config.js +688 -0
  29. package/libs/agent/modules/ai/operations.js +787 -0
  30. package/libs/agent/modules/analyze/api.js +546 -0
  31. package/libs/agent/modules/analyze/dorks.js +395 -0
  32. package/libs/agent/modules/ccard/README.md +454 -0
  33. package/libs/agent/modules/ccard/audit.js +479 -0
  34. package/libs/agent/modules/ccard/checker.js +674 -0
  35. package/libs/agent/modules/ccard/payment-processors.json +16 -0
  36. package/libs/agent/modules/ccard/validator.js +629 -0
  37. package/libs/agent/modules/code/analyzer.js +303 -0
  38. package/libs/agent/modules/code/jquery.js +1093 -0
  39. package/libs/agent/modules/code/react.js +1536 -0
  40. package/libs/agent/modules/code/refactor.js +499 -0
  41. package/libs/agent/modules/crypto/exchange.js +564 -0
  42. package/libs/agent/modules/net/proxy.js +409 -0
  43. package/libs/agent/modules/security/cve.js +442 -0
  44. package/libs/agent/modules/security/monitor.js +360 -0
  45. package/libs/agent/modules/security/scanner.js +300 -0
  46. package/libs/agent/modules/security/vulnerability.js +506 -0
  47. package/libs/agent/modules/security/web.js +465 -0
  48. package/libs/agent/modules/utils/browser.js +492 -0
  49. package/libs/agent/modules/utils/colorizer.js +285 -0
  50. package/libs/agent/modules/utils/manager.js +478 -0
  51. package/libs/cloud/index.js +228 -0
  52. package/libs/config/db.js +21 -0
  53. package/libs/config/validator.js +82 -0
  54. package/libs/db/index.js +318 -0
  55. package/libs/emailer/imap.js +126 -0
  56. package/libs/emailer/info.js +41 -0
  57. package/libs/emailer/smtp.js +77 -0
  58. package/libs/handler/async.js +3 -0
  59. package/libs/handler/error.js +66 -0
  60. package/libs/handler/index.js +161 -0
  61. package/libs/logger/index.js +49 -0
  62. package/libs/logger/morgan.js +24 -0
  63. package/libs/passport/passport.js +109 -0
  64. package/libs/search/api.js +384 -0
  65. package/libs/search/features.js +219 -0
  66. package/libs/search/service.js +64 -0
  67. package/libs/swagger/config.js +18 -0
  68. package/libs/swagger/index.js +35 -0
  69. package/libs/validator/index.js +254 -0
  70. package/models/blog.js +31 -0
  71. package/models/brand.js +12 -0
  72. package/models/cart.js +14 -0
  73. package/models/category.js +11 -0
  74. package/models/coupon.js +9 -0
  75. package/models/customer.js +0 -0
  76. package/models/enquiry.js +29 -0
  77. package/models/events.js +13 -0
  78. package/models/order.js +94 -0
  79. package/models/product.js +32 -0
  80. package/models/review.js +14 -0
  81. package/models/tag.js +10 -0
  82. package/models/task.js +11 -0
  83. package/models/user.js +68 -0
  84. package/package.json +12 -0
  85. package/routes/agent.js +615 -0
  86. package/routes/auth.js +13 -0
  87. package/routes/blog.js +19 -0
  88. package/routes/brand.js +15 -0
  89. package/routes/cart.js +105 -0
  90. package/routes/category.js +16 -0
  91. package/routes/coupon.js +15 -0
  92. package/routes/enquiry.js +14 -0
  93. package/routes/events.js +16 -0
  94. package/routes/mail.js +170 -0
  95. package/routes/order.js +19 -0
  96. package/routes/product.js +22 -0
  97. package/routes/review.js +11 -0
  98. package/routes/task.js +12 -0
  99. package/routes/user.js +17 -0
@@ -0,0 +1,1093 @@
1
+ // modules/code/jquery-to-react.js - jQuery to React Converter
2
+ const fs = require('fs').promises;
3
+ const path = require('path');
4
+ const colorizer = require('../utils/colorizer');
5
+
6
+ const JQueryToReact = function() {
7
+ this.stateVariables = new Map();
8
+ this.refVariables = new Set();
9
+ this.effects = [];
10
+ this.functions = [];
11
+ this.eventHandlers = new Map();
12
+ this.ajaxCalls = [];
13
+ this.animations = [];
14
+ this.hooks = new Set();
15
+ this.componentName = '';
16
+ this.imports = new Set(['React']);
17
+ }
18
+
19
+ JQueryToReact.prototype = {
20
+
21
+ convert(args) {
22
+ const filePath = args[0];
23
+ const outputPath = args[1] || filePath.replace(/\.js$/, '.jsx');
24
+
25
+ if (!filePath) {
26
+ console.log(colorizer.error('Usage: jquery-to-react <jquery-file.js> [output-file.jsx]'));
27
+ console.log(colorizer.info('Examples:'));
28
+ console.log(colorizer.dim(' jquery-to-react script.js'));
29
+ console.log(colorizer.dim(' jquery-to-react old-app.js new-app.jsx\n'));
30
+ return Promise.resolve();
31
+ }
32
+
33
+ console.log(colorizer.header('jQuery to React Converter'));
34
+ console.log(colorizer.separator());
35
+ console.log(colorizer.cyan('Input: ') + colorizer.bright(filePath));
36
+ console.log(colorizer.cyan('Output: ') + colorizer.bright(outputPath));
37
+ console.log();
38
+
39
+ return fs.readFile(filePath, 'utf8')
40
+ .then(code => {
41
+ console.log(colorizer.info('Analyzing jQuery code...'));
42
+
43
+ // Reset state
44
+ this.reset();
45
+
46
+ // Set component name from filename
47
+ this.componentName = this.toPascalCase(
48
+ path.basename(filePath, path.extname(filePath))
49
+ );
50
+
51
+ // Analyze and convert
52
+ const reactCode = this.convertJQueryToReact(code);
53
+
54
+ return fs.writeFile(outputPath, reactCode);
55
+ })
56
+ .then(() => {
57
+ console.log(colorizer.success('\nConversion complete!'));
58
+ console.log(colorizer.cyan('Generated: ') + colorizer.bright(outputPath));
59
+ console.log();
60
+
61
+ this.printConversionSummary();
62
+ })
63
+ .catch(err => {
64
+ console.log(colorizer.error('Conversion failed: ' + err.message));
65
+ if (err.stack) {
66
+ console.log(colorizer.dim(err.stack));
67
+ }
68
+ console.log();
69
+ });
70
+ },
71
+
72
+ reset() {
73
+ this.stateVariables.clear();
74
+ this.refVariables.clear();
75
+ this.effects = [];
76
+ this.functions = [];
77
+ this.eventHandlers.clear();
78
+ this.ajaxCalls = [];
79
+ this.animations = [];
80
+ this.hooks.clear();
81
+ this.imports.clear();
82
+ this.imports.add('React');
83
+ },
84
+
85
+ convertJQueryToReact(jqueryCode) {
86
+ // Clean up the code
87
+ let code = this.cleanCode(jqueryCode);
88
+
89
+ // Extract different patterns
90
+ this.extractVariables(code);
91
+ this.extractDOMReady(code);
92
+ this.extractEventHandlers(code);
93
+ this.extractAjaxCalls(code);
94
+ this.extractAnimations(code);
95
+ this.extractFunctions(code);
96
+ this.extractDOMManipulation(code);
97
+ this.extractSelectors(code);
98
+
99
+ // Generate React component
100
+ return this.generateReactComponent();
101
+ },
102
+
103
+ cleanCode(code) {
104
+ // Remove comments but preserve structure
105
+ code = code.replace(/\/\*[\s\S]*?\*\//g, '');
106
+ code = code.replace(/\/\/.*/g, '');
107
+
108
+ return code;
109
+ },
110
+
111
+ extractVariables(code) {
112
+ // Extract variable declarations
113
+ const varRegex = /(var|let|const)\s+(\w+)\s*=\s*([^;]+);/g;
114
+ let match;
115
+
116
+ while ((match = varRegex.exec(code)) !== null) {
117
+ const [, type, name, value] = match;
118
+
119
+ // Determine if it needs to be state
120
+ if (this.needsState(name, value, code)) {
121
+ this.stateVariables.set(name, {
122
+ initialValue: value.trim(),
123
+ type: 'state'
124
+ });
125
+ this.hooks.add('useState');
126
+ console.log(colorizer.info(' Converting to state: ' + name));
127
+ } else if (this.isConstant(name)) {
128
+ this.stateVariables.set(name, {
129
+ initialValue: value.trim(),
130
+ type: 'const'
131
+ });
132
+ }
133
+ }
134
+ },
135
+
136
+ needsState(varName, value, code) {
137
+ // Check if variable is modified after declaration
138
+ const assignmentRegex = new RegExp(`\\b${varName}\\s*=\\s*[^=]`, 'g');
139
+ const matches = code.match(assignmentRegex);
140
+
141
+ // If modified, needs state
142
+ if (matches && matches.length > 0) {
143
+ return true;
144
+ }
145
+
146
+ // Check if used in DOM manipulation
147
+ const domManipRegex = new RegExp(`${varName}[\\s\\S]*?\\.(?:html|text|val|attr|prop|css|show|hide)\\s*\\(`, 'g');
148
+ if (domManipRegex.test(code)) {
149
+ return true;
150
+ }
151
+
152
+ return false;
153
+ },
154
+
155
+ isConstant(varName) {
156
+ return /^[A-Z_]+$/.test(varName) ||
157
+ varName.startsWith('CONFIG') ||
158
+ varName.startsWith('CONST');
159
+ },
160
+
161
+ extractDOMReady(code) {
162
+ const patterns = [
163
+ /\$\(document\)\.ready\s*\(\s*function\s*\(\)\s*\{([\s\S]*?)\}\s*\)/g,
164
+ /\$\(function\s*\(\)\s*\{([\s\S]*?)\}\s*\)/g,
165
+ /document\.addEventListener\s*\(\s*['"]DOMContentLoaded['"]\s*,\s*function\s*\(\)\s*\{([\s\S]*?)\}\s*\)/g,
166
+ /\$\(document\)\.ready\s*\(\s*\(\)\s*=>\s*\{([\s\S]*?)\}\s*\)/g
167
+ ];
168
+
169
+ patterns.forEach(pattern => {
170
+ let match;
171
+ while ((match = pattern.exec(code)) !== null) {
172
+ const initCode = match[1];
173
+ if (initCode && initCode.trim()) {
174
+ this.effects.push({
175
+ type: 'mount',
176
+ code: this.convertCodeBlock(initCode),
177
+ dependencies: '[]',
178
+ comment: 'Component initialization (converted from $(document).ready)'
179
+ });
180
+ this.hooks.add('useEffect');
181
+ console.log(colorizer.info(' Found DOM ready handler'));
182
+ }
183
+ }
184
+ });
185
+ },
186
+
187
+ extractEventHandlers(code) {
188
+ // Pattern: $('.selector').on('event', handler)
189
+ const onPattern = /\$\(['"](.*?)['"]\)\.on\s*\(\s*['"](\w+)['"]\s*,\s*(function[^}]*\{[\s\S]*?\}|\([^)]*\)\s*=>\s*\{[\s\S]*?\})\s*\)/g;
190
+ let match;
191
+
192
+ while ((match = onPattern.exec(code)) !== null) {
193
+ const [, selector, event, handler] = match;
194
+ this.addEventHandler(selector, event, handler);
195
+ }
196
+
197
+ // Pattern: $('.selector').click(handler)
198
+ const eventMethods = ['click', 'change', 'submit', 'keyup', 'keydown', 'focus', 'blur', 'input', 'mouseover', 'mouseout'];
199
+ eventMethods.forEach(event => {
200
+ const pattern = new RegExp(`\\$\\(['"](.*?)['"]\\)\\.${event}\\s*\\(\\s*(function[^}]*\\{[\\s\\S]*?\\}|\\([^)]*\\)\\s*=>\\s*\\{[\\s\\S]*?\\})\\s*\\)`, 'g');
201
+
202
+ while ((match = pattern.exec(code)) !== null) {
203
+ const [, selector, handler] = match;
204
+ this.addEventHandler(selector, event, handler);
205
+ }
206
+ });
207
+
208
+ // Pattern: $(selector).on('event', '.child', handler) - event delegation
209
+ const delegationPattern = /\$\(['"](.*?)['"]\)\.on\s*\(\s*['"](\w+)['"]\s*,\s*['"](.*?)['"]\s*,\s*(function[^}]*\{[\s\S]*?\}|\([^)]*\)\s*=>\s*\{[\s\S]*?\})\s*\)/g;
210
+
211
+ while ((match = delegationPattern.exec(code)) !== null) {
212
+ const [, parentSelector, event, childSelector, handler] = match;
213
+ this.addEventHandler(childSelector, event, handler, parentSelector);
214
+ }
215
+ },
216
+
217
+ addEventHandler(selector, event, handler, parentSelector = null) {
218
+ const refName = this.selectorToRefName(selector);
219
+ const handlerName = this.generateHandlerName(selector, event);
220
+ const convertedHandler = this.convertFunctionBody(handler);
221
+
222
+ this.refVariables.add(refName);
223
+ this.hooks.add('useRef');
224
+
225
+ this.eventHandlers.set(handlerName, {
226
+ selector,
227
+ event,
228
+ refName,
229
+ handler: convertedHandler,
230
+ parentSelector
231
+ });
232
+
233
+ // Add effect to attach event listener
234
+ this.effects.push({
235
+ type: 'event',
236
+ code: this.generateEventEffect(refName, event, handlerName),
237
+ dependencies: `[${this.extractHandlerDependencies(convertedHandler).join(', ')}]`,
238
+ comment: `Event listener for ${event} on ${selector}`
239
+ });
240
+
241
+ this.hooks.add('useEffect');
242
+ console.log(colorizer.info(` Found event handler: ${selector}.${event}()`));
243
+ },
244
+
245
+ extractAjaxCalls(code) {
246
+ // $.ajax() calls
247
+ const ajaxPattern = /\$\.ajax\s*\(\s*\{([\s\S]*?)\}\s*\)/g;
248
+ let match;
249
+
250
+ while ((match = ajaxPattern.exec(code)) !== null) {
251
+ const config = this.parseAjaxConfig(match[1]);
252
+ this.ajaxCalls.push({
253
+ type: 'ajax',
254
+ config,
255
+ converted: this.convertAjaxToFetch(config)
256
+ });
257
+ console.log(colorizer.info(' Found $.ajax() call'));
258
+ }
259
+
260
+ // $.get() calls
261
+ const getPattern = /\$\.get\s*\(\s*['"](.*?)['"]\s*,?\s*(function[^}]*\{[\s\S]*?\}|\([^)]*\)\s*=>\s*\{[\s\S]*?\})?\s*\)/g;
262
+
263
+ while ((match = getPattern.exec(code)) !== null) {
264
+ const [, url, callback] = match;
265
+ this.ajaxCalls.push({
266
+ type: 'get',
267
+ url,
268
+ callback: callback ? this.convertFunctionBody(callback) : null,
269
+ converted: this.convertGetToFetch(url, callback)
270
+ });
271
+ console.log(colorizer.info(' Found $.get() call'));
272
+ }
273
+
274
+ // $.post() calls
275
+ const postPattern = /\$\.post\s*\(\s*['"](.*?)['"]\s*,\s*([^,]+)\s*,?\s*(function[^}]*\{[\s\S]*?\}|\([^)]*\)\s*=>\s*\{[\s\S]*?\})?\s*\)/g;
276
+
277
+ while ((match = postPattern.exec(code)) !== null) {
278
+ const [, url, data, callback] = match;
279
+ this.ajaxCalls.push({
280
+ type: 'post',
281
+ url,
282
+ data,
283
+ callback: callback ? this.convertFunctionBody(callback) : null,
284
+ converted: this.convertPostToFetch(url, data, callback)
285
+ });
286
+ console.log(colorizer.info(' Found $.post() call'));
287
+ }
288
+
289
+ if (this.ajaxCalls.length > 0) {
290
+ this.hooks.add('useEffect');
291
+ this.hooks.add('useState');
292
+ }
293
+ },
294
+
295
+ parseAjaxConfig(configStr) {
296
+ const config = {};
297
+
298
+ // Extract URL
299
+ const urlMatch = configStr.match(/url\s*:\s*['"](.*?)['"]/);
300
+ if (urlMatch) config.url = urlMatch[1];
301
+
302
+ // Extract method
303
+ const methodMatch = configStr.match(/(?:method|type)\s*:\s*['"](.*?)['"]/i);
304
+ if (methodMatch) config.method = methodMatch[1].toUpperCase();
305
+
306
+ // Extract data
307
+ const dataMatch = configStr.match(/data\s*:\s*([^,}]+)/);
308
+ if (dataMatch) config.data = dataMatch[1].trim();
309
+
310
+ // Extract success callback
311
+ const successMatch = configStr.match(/success\s*:\s*(function[^}]*\{[\s\S]*?\}|\([^)]*\)\s*=>\s*\{[\s\S]*?\})/);
312
+ if (successMatch) config.success = this.convertFunctionBody(successMatch[1]);
313
+
314
+ // Extract error callback
315
+ const errorMatch = configStr.match(/error\s*:\s*(function[^}]*\{[\s\S]*?\}|\([^)]*\)\s*=>\s*\{[\s\S]*?\})/);
316
+ if (errorMatch) config.error = this.convertFunctionBody(errorMatch[1]);
317
+
318
+ return config;
319
+ },
320
+
321
+ convertAjaxToFetch(config) {
322
+ let code = `fetch('${config.url || 'URL_HERE'}', {\n`;
323
+ code += ` method: '${config.method || 'GET'}',\n`;
324
+
325
+ if (config.data) {
326
+ code += ` headers: { 'Content-Type': 'application/json' },\n`;
327
+ code += ` body: JSON.stringify(${config.data})\n`;
328
+ }
329
+
330
+ code += `})\n`;
331
+ code += ` .then(response => response.json())\n`;
332
+
333
+ if (config.success) {
334
+ code += ` .then(data => {\n ${config.success}\n })\n`;
335
+ } else {
336
+ code += ` .then(data => {\n // Handle success\n console.log(data);\n })\n`;
337
+ }
338
+
339
+ if (config.error) {
340
+ code += ` .catch(error => {\n ${config.error}\n });\n`;
341
+ } else {
342
+ code += ` .catch(error => {\n console.error('Error:', error);\n });\n`;
343
+ }
344
+
345
+ return code;
346
+ },
347
+
348
+ convertGetToFetch(url, callback) {
349
+ let code = `fetch('${url}')\n`;
350
+ code += ` .then(response => response.json())\n`;
351
+
352
+ if (callback) {
353
+ code += ` .then(data => {\n ${callback}\n })\n`;
354
+ } else {
355
+ code += ` .then(data => {\n // Handle response\n console.log(data);\n })\n`;
356
+ }
357
+
358
+ code += ` .catch(error => console.error('Error:', error));\n`;
359
+
360
+ return code;
361
+ },
362
+
363
+ convertPostToFetch(url, data, callback) {
364
+ let code = `fetch('${url}', {\n`;
365
+ code += ` method: 'POST',\n`;
366
+ code += ` headers: { 'Content-Type': 'application/json' },\n`;
367
+ code += ` body: JSON.stringify(${data})\n`;
368
+ code += `})\n`;
369
+ code += ` .then(response => response.json())\n`;
370
+
371
+ if (callback) {
372
+ code += ` .then(data => {\n ${callback}\n })\n`;
373
+ } else {
374
+ code += ` .then(data => {\n // Handle response\n console.log(data);\n })\n`;
375
+ }
376
+
377
+ code += ` .catch(error => console.error('Error:', error));\n`;
378
+
379
+ return code;
380
+ },
381
+
382
+ extractAnimations(code) {
383
+ const animMethods = ['show', 'hide', 'toggle', 'fadeIn', 'fadeOut', 'fadeToggle', 'slideUp', 'slideDown', 'slideToggle', 'animate'];
384
+
385
+ animMethods.forEach(method => {
386
+ const pattern = new RegExp(`\\$\\(['"](.*?)['"]\\)\\.${method}\\s*\\(([^)]*)\\)`, 'g');
387
+ let match;
388
+
389
+ while ((match = pattern.exec(code)) !== null) {
390
+ const [, selector, args] = match;
391
+ this.animations.push({
392
+ selector,
393
+ method,
394
+ args: args.trim(),
395
+ suggestion: this.getAnimationSuggestion(method)
396
+ });
397
+ console.log(colorizer.warning(` Found animation: ${selector}.${method}() - requires CSS/library`));
398
+ }
399
+ });
400
+ },
401
+
402
+ getAnimationSuggestion(method) {
403
+ const suggestions = {
404
+ 'show': 'Use CSS display or visibility with state',
405
+ 'hide': 'Use CSS display or visibility with state',
406
+ 'toggle': 'Toggle visibility state with conditional rendering',
407
+ 'fadeIn': 'Use CSS transition with opacity',
408
+ 'fadeOut': 'Use CSS transition with opacity',
409
+ 'fadeToggle': 'Toggle opacity state with CSS transition',
410
+ 'slideUp': 'Use CSS transition with max-height',
411
+ 'slideDown': 'Use CSS transition with max-height',
412
+ 'slideToggle': 'Toggle height state with CSS transition',
413
+ 'animate': 'Use CSS animations or libraries like Framer Motion, React Spring'
414
+ };
415
+
416
+ return suggestions[method] || 'Convert to CSS animations or use animation library';
417
+ },
418
+
419
+ extractFunctions(code) {
420
+ // Regular function declarations
421
+ const funcPattern = /function\s+(\w+)\s*\(([^)]*)\)\s*\{([\s\S]*?)\n\}/g;
422
+ let match;
423
+
424
+ while ((match = funcPattern.exec(code)) !== null) {
425
+ const [, name, params, body] = match;
426
+
427
+ // Skip if it's an event handler (already extracted)
428
+ if (!Array.from(this.eventHandlers.keys()).some(h => h.includes(name))) {
429
+ this.functions.push({
430
+ name,
431
+ params: params.trim(),
432
+ body: this.convertFunctionBody(body),
433
+ isAsync: this.containsAjax(body)
434
+ });
435
+ console.log(colorizer.info(` Found function: ${name}()`));
436
+ }
437
+ }
438
+
439
+ // Arrow function assignments
440
+ const arrowPattern = /(?:const|let|var)\s+(\w+)\s*=\s*\(([^)]*)\)\s*=>\s*\{([\s\S]*?)\n\}/g;
441
+
442
+ while ((match = arrowPattern.exec(code)) !== null) {
443
+ const [, name, params, body] = match;
444
+
445
+ if (!Array.from(this.eventHandlers.keys()).some(h => h.includes(name))) {
446
+ this.functions.push({
447
+ name,
448
+ params: params.trim(),
449
+ body: this.convertFunctionBody(body),
450
+ isAsync: this.containsAjax(body),
451
+ isArrow: true
452
+ });
453
+ console.log(colorizer.info(` Found arrow function: ${name}()`));
454
+ }
455
+ }
456
+ },
457
+
458
+ containsAjax(code) {
459
+ return /\$\.(ajax|get|post)|fetch\(/.test(code);
460
+ },
461
+
462
+ extractDOMManipulation(code) {
463
+ // .html()
464
+ const htmlPattern = /\$\(['"](.*?)['"]\)\.html\s*\(\s*([^)]+)\s*\)/g;
465
+ let match;
466
+
467
+ while ((match = htmlPattern.exec(code)) !== null) {
468
+ const [, selector, content] = match;
469
+ const varName = this.selectorToStateName(selector);
470
+
471
+ this.stateVariables.set(varName, {
472
+ initialValue: "''",
473
+ type: 'state',
474
+ purpose: 'DOM content'
475
+ });
476
+ this.hooks.add('useState');
477
+ console.log(colorizer.info(` Converting .html() to state: ${varName}`));
478
+ }
479
+
480
+ // .text()
481
+ const textPattern = /\$\(['"](.*?)['"]\)\.text\s*\(\s*([^)]+)\s*\)/g;
482
+
483
+ while ((match = textPattern.exec(code)) !== null) {
484
+ const [, selector, content] = match;
485
+ const varName = this.selectorToStateName(selector);
486
+
487
+ this.stateVariables.set(varName, {
488
+ initialValue: "''",
489
+ type: 'state',
490
+ purpose: 'Text content'
491
+ });
492
+ this.hooks.add('useState');
493
+ console.log(colorizer.info(` Converting .text() to state: ${varName}`));
494
+ }
495
+
496
+ // .val()
497
+ const valPattern = /\$\(['"](.*?)['"]\)\.val\s*\(\s*([^)]*)\s*\)/g;
498
+
499
+ while ((match = valPattern.exec(code)) !== null) {
500
+ const [, selector, value] = match;
501
+ const varName = this.selectorToStateName(selector);
502
+
503
+ this.stateVariables.set(varName, {
504
+ initialValue: "''",
505
+ type: 'state',
506
+ purpose: 'Form input value'
507
+ });
508
+ this.hooks.add('useState');
509
+ console.log(colorizer.info(` Converting .val() to controlled input: ${varName}`));
510
+ }
511
+
512
+ // .show() / .hide()
513
+ const visibilityPattern = /\$\(['"](.*?)['"]\)\.(show|hide)\s*\(/g;
514
+
515
+ while ((match = visibilityPattern.exec(code)) !== null) {
516
+ const [, selector, method] = match;
517
+ const varName = `${this.selectorToStateName(selector)}Visible`;
518
+
519
+ this.stateVariables.set(varName, {
520
+ initialValue: method === 'show' ? 'true' : 'false',
521
+ type: 'state',
522
+ purpose: 'Visibility toggle'
523
+ });
524
+ this.hooks.add('useState');
525
+ console.log(colorizer.info(` Converting .${method}() to state: ${varName}`));
526
+ }
527
+
528
+ // .addClass() / .removeClass() / .toggleClass()
529
+ const classPattern = /\$\(['"](.*?)['"]\)\.(addClass|removeClass|toggleClass)\s*\(\s*['"](.*?)['"]\s*\)/g;
530
+
531
+ while ((match = classPattern.exec(code)) !== null) {
532
+ const [, selector, method, className] = match;
533
+ const varName = `${this.selectorToStateName(selector)}Class`;
534
+
535
+ this.stateVariables.set(varName, {
536
+ initialValue: "''",
537
+ type: 'state',
538
+ purpose: `CSS class management for ${className}`
539
+ });
540
+ this.hooks.add('useState');
541
+ console.log(colorizer.info(` Converting .${method}() to className state: ${varName}`));
542
+ }
543
+ },
544
+
545
+ extractSelectors(code) {
546
+ // Extract all jQuery selectors that aren't already handled
547
+ const selectorPattern = /\$\(['"]((?:#|\.)?[\w-]+)['"]\)/g;
548
+ let match;
549
+
550
+ const seenSelectors = new Set();
551
+
552
+ while ((match = selectorPattern.exec(code)) !== null) {
553
+ const selector = match[1];
554
+
555
+ if (!seenSelectors.has(selector) && selector.startsWith('#')) {
556
+ const refName = this.selectorToRefName(selector);
557
+ this.refVariables.add(refName);
558
+ this.hooks.add('useRef');
559
+ seenSelectors.add(selector);
560
+ console.log(colorizer.info(` Creating ref for selector: ${selector}`));
561
+ }
562
+ }
563
+ },
564
+
565
+ convertCodeBlock(code) {
566
+ let converted = code;
567
+
568
+ // Convert jQuery selectors to refs
569
+ converted = converted.replace(
570
+ /\$\(['"]#([\w-]+)['"]\)/g,
571
+ (match, id) => {
572
+ const refName = this.toCamelCase(id);
573
+ return `${refName}Ref.current`;
574
+ }
575
+ );
576
+
577
+ // Convert class selectors
578
+ converted = converted.replace(
579
+ /\$\(['"]\.([\w-]+)['"]\)/g,
580
+ (match, className) => {
581
+ return `// TODO: Use ref or state for .${className}`;
582
+ }
583
+ );
584
+
585
+ // Convert .html()
586
+ converted = converted.replace(
587
+ /\.html\s*\(\s*([^)]+)\s*\)/g,
588
+ (match, content) => {
589
+ return `// TODO: Use state or dangerouslySetInnerHTML`;
590
+ }
591
+ );
592
+
593
+ // Convert .text()
594
+ converted = converted.replace(
595
+ /\.text\s*\(\s*([^)]+)\s*\)/g,
596
+ (match, content) => {
597
+ return `// TODO: Use state to set text content`;
598
+ }
599
+ );
600
+
601
+ // Convert .val()
602
+ converted = converted.replace(
603
+ /\.val\s*\(\s*([^)]*)\s*\)/g,
604
+ (match, value) => {
605
+ if (value) {
606
+ return `// TODO: Use setState to update input value`;
607
+ } else {
608
+ return `.value // TODO: Use state instead`;
609
+ }
610
+ }
611
+ );
612
+
613
+ // Convert .show() / .hide()
614
+ converted = converted.replace(
615
+ /\.(show|hide)\s*\(\)/g,
616
+ '// TODO: Use state to toggle visibility'
617
+ );
618
+
619
+ // Convert .addClass() / .removeClass()
620
+ converted = converted.replace(
621
+ /\.(addClass|removeClass|toggleClass)\s*\([^)]+\)/g,
622
+ '// TODO: Use className state'
623
+ );
624
+
625
+ // Convert .css()
626
+ converted = converted.replace(
627
+ /\.css\s*\([^)]+\)/g,
628
+ '// TODO: Use inline style or CSS classes'
629
+ );
630
+
631
+ // Convert this to proper context
632
+ converted = converted.replace(/\bthis\./g, '');
633
+
634
+ return converted.trim();
635
+ },
636
+
637
+ convertFunctionBody(funcStr) {
638
+ // Extract function body
639
+ const bodyMatch = funcStr.match(/\{([\s\S]*)\}/);
640
+ if (!bodyMatch) return funcStr;
641
+
642
+ return this.convertCodeBlock(bodyMatch[1]);
643
+ },
644
+
645
+ generateEventEffect(refName, event, handlerName) {
646
+ let code = `const element = ${refName}Ref.current;\n`;
647
+ code += `if (element) {\n`;
648
+ code += ` element.addEventListener('${event}', ${handlerName});\n`;
649
+ code += ` return () => element.removeEventListener('${event}', ${handlerName});\n`;
650
+ code += `}`;
651
+
652
+ return code;
653
+ },
654
+
655
+ extractHandlerDependencies(handlerCode) {
656
+ const deps = [];
657
+
658
+ // Find state variables used in handler
659
+ this.stateVariables.forEach((value, key) => {
660
+ if (value.type === 'state' && handlerCode.includes(key)) {
661
+ deps.push(key);
662
+ }
663
+ });
664
+
665
+ return deps;
666
+ },
667
+
668
+ generateHandlerName(selector, event) {
669
+ const selectorName = this.selectorToRefName(selector);
670
+ const eventName = this.toPascalCase(event);
671
+ return `handle${selectorName}${eventName}`;
672
+ },
673
+
674
+ selectorToRefName(selector) {
675
+ return selector
676
+ .replace(/^[#.]/, '')
677
+ .replace(/[^a-zA-Z0-9]/g, '_')
678
+ .replace(/_+/g, '_')
679
+ .replace(/^_|_$/g, '')
680
+ .replace(/^(.)/, (_, c) => c.toLowerCase());
681
+ },
682
+
683
+ selectorToStateName(selector) {
684
+ return this.toCamelCase(
685
+ selector
686
+ .replace(/^[#.]/, '')
687
+ .replace(/[^a-zA-Z0-9]/g, '_')
688
+ );
689
+ },
690
+
691
+ generateReactComponent() {
692
+ let code = '';
693
+
694
+ // Imports
695
+ const hooks = Array.from(this.hooks).filter(h => h !== 'React');
696
+ if (hooks.length > 0) {
697
+ code += `import React, { ${hooks.join(', ')} } from 'react';\n`;
698
+ } else {
699
+ code += `import React from 'react';\n`;
700
+ }
701
+
702
+ code += '\n';
703
+
704
+ // Component
705
+ code += `function ${this.componentName}() {\n`;
706
+
707
+ // State variables
708
+ if (this.stateVariables.size > 0) {
709
+ code += ' // State\n';
710
+ this.stateVariables.forEach((value, key) => {
711
+ if (value.type === 'state') {
712
+ const setterName = `set${this.toPascalCase(key)}`;
713
+ code += ` const [${key}, ${setterName}] = useState(${value.initialValue});`;
714
+ if (value.purpose) {
715
+ code += ` // ${value.purpose}`;
716
+ }
717
+ code += '\n';
718
+ } else if (value.type === 'const') {
719
+ code += ` const ${key} = ${value.initialValue};\n`;
720
+ }
721
+ });
722
+ code += '\n';
723
+ }
724
+
725
+ // Refs
726
+ if (this.refVariables.size > 0) {
727
+ code += ' // Refs\n';
728
+ this.refVariables.forEach(refName => {
729
+ code += ` const ${refName}Ref = useRef(null);\n`;
730
+ });
731
+ code += '\n';
732
+ }
733
+
734
+ // Event handlers
735
+ if (this.eventHandlers.size > 0) {
736
+ code += ' // Event Handlers\n';
737
+ this.eventHandlers.forEach((handler, name) => {
738
+ code += ` const ${name} = (e) => {\n`;
739
+ code += ` ${handler.handler.split('\n').join('\n ')}\n`;
740
+ code += ` };\n\n`;
741
+ });
742
+ }
743
+
744
+ // Functions
745
+ if (this.functions.length > 0) {
746
+ code += ' // Functions\n';
747
+ this.functions.forEach(func => {
748
+ const asyncKeyword = func.isAsync ? 'async ' : '';
749
+ code += ` const ${func.name} = ${asyncKeyword}(${func.params}) => {\n`;
750
+ code += ` ${func.body.split('\n').join('\n ')}\n`;
751
+ code += ` };\n\n`;
752
+ });
753
+ }
754
+
755
+ // Effects
756
+ if (this.effects.length > 0) {
757
+ code += ' // Effects\n';
758
+ this.effects.forEach(effect => {
759
+ if (effect.comment) {
760
+ code += ` // ${effect.comment}\n`;
761
+ }
762
+ code += ` useEffect(() => {\n`;
763
+ code += ` ${effect.code.split('\n').join('\n ')}\n`;
764
+ code += ` }, ${effect.dependencies});\n\n`;
765
+ });
766
+ }
767
+
768
+ // AJAX calls in useEffect (if not already in effects)
769
+ if (this.ajaxCalls.length > 0) {
770
+ const standaloneAjax = this.ajaxCalls.filter(ajax =>
771
+ !this.effects.some(e => e.code.includes('fetch'))
772
+ );
773
+
774
+ if (standaloneAjax.length > 0) {
775
+ code += ' // Data Fetching\n';
776
+ code += ' useEffect(() => {\n';
777
+ standaloneAjax.forEach(ajax => {
778
+ code += ` // Converted from ${ajax.type}\n`;
779
+ code += ` ${ajax.converted.split('\n').join('\n ')}\n`;
780
+ });
781
+ code += ' }, []);\n\n';
782
+ }
783
+ }
784
+
785
+ // Return JSX
786
+ code += ' return (\n';
787
+ code += ' <div className="' + this.componentName.toLowerCase() + '">\n';
788
+ code += ' {/* TODO: Add your JSX here */}\n';
789
+
790
+ // Add ref examples
791
+ if (this.refVariables.size > 0) {
792
+ code += ' {/* Example refs: */}\n';
793
+ this.refVariables.forEach(refName => {
794
+ code += ` {/* <div ref={${refName}Ref}>...</div> */}\n`;
795
+ });
796
+ }
797
+
798
+ // Add conditional rendering examples
799
+ const visibilityStates = Array.from(this.stateVariables.entries())
800
+ .filter(([key, val]) => val.purpose && val.purpose.includes('Visibility'));
801
+
802
+ if (visibilityStates.length > 0) {
803
+ code += ' {/* Conditional rendering: */}\n';
804
+ visibilityStates.forEach(([key]) => {
805
+ code += ` {/* {${key} && <div>Visible content</div>} */}\n`;
806
+ });
807
+ }
808
+
809
+ // Add controlled input examples
810
+ const inputStates = Array.from(this.stateVariables.entries())
811
+ .filter(([key, val]) => val.purpose && val.purpose.includes('input'));
812
+
813
+ if (inputStates.length > 0) {
814
+ code += ' {/* Controlled inputs: */}\n';
815
+ inputStates.forEach(([key]) => {
816
+ const setterName = `set${this.toPascalCase(key)}`;
817
+ code += ` {/* <input value={${key}} onChange={(e) => ${setterName}(e.target.value)} /> */}\n`;
818
+ });
819
+ }
820
+
821
+ code += ' </div>\n';
822
+ code += ' );\n';
823
+ code += '}\n\n';
824
+ code += `export default ${this.componentName};\n`;
825
+
826
+ // Add conversion notes
827
+ code += '\n/* CONVERSION NOTES:\n';
828
+ code += ' * \n';
829
+ code += ' * 1. All jQuery selectors have been converted to refs or state\n';
830
+ code += ' * 2. Event handlers are attached using useEffect with cleanup\n';
831
+ code += ' * 3. DOM manipulations should use state instead\n';
832
+ code += ' * 4. AJAX calls converted to fetch API\n';
833
+
834
+ if (this.animations.length > 0) {
835
+ code += ' * \n';
836
+ code += ' * ANIMATIONS DETECTED:\n';
837
+ this.animations.forEach(anim => {
838
+ code += ` * - ${anim.selector}.${anim.method}() => ${anim.suggestion}\n`;
839
+ });
840
+ }
841
+
842
+ code += ' * \n';
843
+ code += ' * TODO Items:\n';
844
+ code += ' * - Review all TODO comments in the code\n';
845
+ code += ' * - Add proper JSX structure\n';
846
+ code += ' * - Test event handlers\n';
847
+ code += ' * - Verify state updates work correctly\n';
848
+ code += ' * - Add error handling for async operations\n';
849
+
850
+ if (this.animations.length > 0) {
851
+ code += ' * - Implement animations with CSS or animation library\n';
852
+ }
853
+
854
+ code += ' */\n';
855
+
856
+ return code;
857
+ },
858
+
859
+ printConversionSummary() {
860
+ console.log(colorizer.section('Conversion Summary'));
861
+ console.log(colorizer.cyan(' Component Name: ') + colorizer.bright(this.componentName));
862
+ console.log(colorizer.cyan(' State Variables: ') + this.stateVariables.size);
863
+ console.log(colorizer.cyan(' Refs: ') + this.refVariables.size);
864
+ console.log(colorizer.cyan(' Event Handlers: ') + this.eventHandlers.size);
865
+ console.log(colorizer.cyan(' Functions: ') + this.functions.length);
866
+ console.log(colorizer.cyan(' Effects: ') + this.effects.length);
867
+ console.log(colorizer.cyan(' AJAX Calls: ') + this.ajaxCalls.length);
868
+ console.log(colorizer.cyan(' Animations: ') + this.animations.length);
869
+ console.log(colorizer.cyan(' Hooks Used: ') + Array.from(this.hooks).join(', '));
870
+
871
+ if (this.animations.length > 0) {
872
+ console.log();
873
+ console.log(colorizer.warning('⚠ Animations detected - will need CSS or animation library'));
874
+ }
875
+
876
+ console.log();
877
+ console.log(colorizer.magenta('Next Steps:'));
878
+ console.log(colorizer.bullet('Review the generated component'));
879
+ console.log(colorizer.bullet('Add JSX structure'));
880
+ console.log(colorizer.bullet('Test functionality'));
881
+ console.log(colorizer.bullet('Address all TODO comments'));
882
+ console.log();
883
+ },
884
+
885
+ analyzeBatch(args) {
886
+ const inputDir = args[0] || '.';
887
+
888
+ console.log(colorizer.header('jQuery Files Analysis'));
889
+ console.log(colorizer.separator());
890
+ console.log(colorizer.cyan('Directory: ') + colorizer.bright(inputDir));
891
+ console.log();
892
+
893
+ return this.findJQueryFiles(inputDir)
894
+ .then(files => {
895
+ if (files.length === 0) {
896
+ console.log(colorizer.warning('No jQuery files found\n'));
897
+ return;
898
+ }
899
+
900
+ console.log(colorizer.info('Found ' + files.length + ' file(s) with jQuery\n'));
901
+
902
+ const analyses = [];
903
+
904
+ return Promise.all(files.map(file => {
905
+ return fs.readFile(file, 'utf8')
906
+ .then(code => {
907
+ const analysis = this.analyzeJQueryFile(code, file);
908
+ analyses.push({ file, analysis });
909
+ });
910
+ }))
911
+ .then(() => {
912
+ this.printBatchAnalysis(analyses);
913
+ });
914
+ })
915
+ .catch(err => {
916
+ console.log(colorizer.error('Analysis failed: ' + err.message + '\n'));
917
+ });
918
+ },
919
+
920
+ findJQueryFiles(dir, files = []) {
921
+ return fs.readdir(dir, { withFileTypes: true })
922
+ .then(items => {
923
+ const promises = items.map(item => {
924
+ const fullPath = path.join(dir, item.name);
925
+
926
+ if (['node_modules', '.git', 'dist', 'build'].includes(item.name)) {
927
+ return Promise.resolve();
928
+ }
929
+
930
+ if (item.isDirectory()) {
931
+ return this.findJQueryFiles(fullPath, files);
932
+ } else if (item.isFile() && path.extname(item.name).toLowerCase() === '.js') {
933
+ return fs.readFile(fullPath, 'utf8')
934
+ .then(content => {
935
+ if (this.containsJQuery(content)) {
936
+ files.push(fullPath);
937
+ }
938
+ })
939
+ .catch(() => {});
940
+ }
941
+
942
+ return Promise.resolve();
943
+ });
944
+
945
+ return Promise.all(promises);
946
+ })
947
+ .then(() => files)
948
+ .catch(() => files);
949
+ },
950
+
951
+ containsJQuery(code) {
952
+ return /\$\(|\$\./g.test(code) || code.includes('jQuery');
953
+ },
954
+
955
+ analyzeJQueryFile(code, filePath) {
956
+ const analysis = {
957
+ selectors: this.countMatches(code, /\$\(['"]/g),
958
+ eventHandlers: this.countMatches(code, /\.(on|click|change|submit|keyup|keydown|focus|blur)\s*\(/g),
959
+ domManipulation: this.countMatches(code, /\.(html|text|val|append|prepend|remove)\s*\(/g),
960
+ ajax: this.countMatches(code, /\$\.(ajax|get|post)/g),
961
+ animations: this.countMatches(code, /\.(show|hide|toggle|fade|slide|animate)\s*\(/g),
962
+ cssManipulation: this.countMatches(code, /\.(css|addClass|removeClass|toggleClass)\s*\(/g),
963
+ complexity: 0
964
+ };
965
+
966
+ // Calculate complexity score
967
+ analysis.complexity =
968
+ analysis.selectors * 1 +
969
+ analysis.eventHandlers * 2 +
970
+ analysis.domManipulation * 2 +
971
+ analysis.ajax * 3 +
972
+ analysis.animations * 2 +
973
+ analysis.cssManipulation * 1;
974
+
975
+ return analysis;
976
+ },
977
+
978
+ countMatches(code, regex) {
979
+ const matches = code.match(regex);
980
+ return matches ? matches.length : 0;
981
+ },
982
+
983
+ printBatchAnalysis(analyses) {
984
+ console.log(colorizer.section('Batch Analysis Results'));
985
+ console.log();
986
+
987
+ analyses.forEach(({ file, analysis }) => {
988
+ const fileName = path.basename(file);
989
+ const complexityLevel =
990
+ analysis.complexity > 20 ? colorizer.red('High') :
991
+ analysis.complexity > 10 ? colorizer.yellow('Medium') :
992
+ colorizer.green('Low');
993
+
994
+ console.log(colorizer.bright(fileName));
995
+ console.log(colorizer.cyan(' Selectors: ') + analysis.selectors);
996
+ console.log(colorizer.cyan(' Event Handlers: ') + analysis.eventHandlers);
997
+ console.log(colorizer.cyan(' DOM Manipulation: ') + analysis.domManipulation);
998
+ console.log(colorizer.cyan(' AJAX Calls: ') + analysis.ajax);
999
+ console.log(colorizer.cyan(' Animations: ') + analysis.animations);
1000
+ console.log(colorizer.cyan(' CSS Manipulation: ') + analysis.cssManipulation);
1001
+ console.log(colorizer.cyan(' Complexity: ') + complexityLevel + ' (' + analysis.complexity + ')');
1002
+ console.log();
1003
+ });
1004
+
1005
+ const totals = analyses.reduce((acc, { analysis }) => ({
1006
+ selectors: acc.selectors + analysis.selectors,
1007
+ eventHandlers: acc.eventHandlers + analysis.eventHandlers,
1008
+ domManipulation: acc.domManipulation + analysis.domManipulation,
1009
+ ajax: acc.ajax + analysis.ajax,
1010
+ animations: acc.animations + analysis.animations,
1011
+ cssManipulation: acc.cssManipulation + analysis.cssManipulation
1012
+ }), {
1013
+ selectors: 0,
1014
+ eventHandlers: 0,
1015
+ domManipulation: 0,
1016
+ ajax: 0,
1017
+ animations: 0,
1018
+ cssManipulation: 0
1019
+ });
1020
+
1021
+ console.log(colorizer.section('Totals'));
1022
+ console.log(colorizer.cyan(' Total Files: ') + analyses.length);
1023
+ console.log(colorizer.cyan(' Total Selectors: ') + totals.selectors);
1024
+ console.log(colorizer.cyan(' Total Event Handlers: ') + totals.eventHandlers);
1025
+ console.log(colorizer.cyan(' Total DOM Manipulations: ') + totals.domManipulation);
1026
+ console.log(colorizer.cyan(' Total AJAX Calls: ') + totals.ajax);
1027
+ console.log(colorizer.cyan(' Total Animations: ') + totals.animations);
1028
+ console.log();
1029
+ },
1030
+
1031
+ convertBatch(args) {
1032
+ const inputDir = args[0] || '.';
1033
+ const outputDir = args[1] || './react-components';
1034
+
1035
+ console.log(colorizer.header('Batch jQuery to React Conversion'));
1036
+ console.log(colorizer.separator());
1037
+ console.log(colorizer.cyan('Input Directory: ') + colorizer.bright(inputDir));
1038
+ console.log(colorizer.cyan('Output Directory: ') + colorizer.bright(outputDir));
1039
+ console.log();
1040
+
1041
+ return this.findJQueryFiles(inputDir)
1042
+ .then(files => {
1043
+ if (files.length === 0) {
1044
+ console.log(colorizer.warning('No jQuery files found\n'));
1045
+ return;
1046
+ }
1047
+
1048
+ console.log(colorizer.info('Found ' + files.length + ' file(s) to convert\n'));
1049
+
1050
+ return fs.mkdir(outputDir, { recursive: true })
1051
+ .then(() => {
1052
+ const promises = files.map(file => {
1053
+ const relativePath = path.relative(inputDir, file);
1054
+ const outputFile = path.join(
1055
+ outputDir,
1056
+ relativePath.replace(/\.js$/, '.jsx')
1057
+ );
1058
+
1059
+ console.log(colorizer.cyan('Converting: ') + relativePath);
1060
+
1061
+ return this.convert([file, outputFile])
1062
+ .catch(err => {
1063
+ console.log(colorizer.warning('Failed: ' + err.message));
1064
+ });
1065
+ });
1066
+
1067
+ return Promise.all(promises);
1068
+ });
1069
+ })
1070
+ .then(() => {
1071
+ console.log(colorizer.success('\nBatch conversion complete!\n'));
1072
+ })
1073
+ .catch(err => {
1074
+ console.log(colorizer.error('Batch conversion failed: ' + err.message + '\n'));
1075
+ });
1076
+ },
1077
+
1078
+ toPascalCase(str) {
1079
+ return str
1080
+ .replace(/[-_\s]+(.)?/g, (_, c) => c ? c.toUpperCase() : '')
1081
+ .replace(/^(.)/, (_, c) => c.toUpperCase())
1082
+ .replace(/[^a-zA-Z0-9]/g, '');
1083
+ },
1084
+
1085
+ toCamelCase(str) {
1086
+ return str
1087
+ .replace(/[-_\s]+(.)?/g, (_, c) => c ? c.toUpperCase() : '')
1088
+ .replace(/^(.)/, (_, c) => c.toLowerCase())
1089
+ .replace(/[^a-zA-Z0-9]/g, '');
1090
+ }
1091
+ };
1092
+
1093
+ module.exports = JQueryToReact;