lwc-convert 1.0.0 → 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.
@@ -29,23 +29,23 @@ function generateAuraToLwcTests(markup, transformedMarkup, controller) {
29
29
  imports.push(`import ${channelVar} from '@salesforce/messageChannel/${lms.channelName}';`);
30
30
  }
31
31
  // Add LMS mocks
32
- mocks.push(`// Mock LMS
33
- jest.mock(
34
- 'lightning/messageService',
35
- () => ({
36
- publish: jest.fn(),
37
- subscribe: jest.fn(() => ({ unsubscribe: jest.fn() })),
38
- unsubscribe: jest.fn(),
39
- MessageContext: jest.fn()
40
- }),
41
- { virtual: true }
32
+ mocks.push(`// Mock LMS
33
+ jest.mock(
34
+ 'lightning/messageService',
35
+ () => ({
36
+ publish: jest.fn(),
37
+ subscribe: jest.fn(() => ({ unsubscribe: jest.fn() })),
38
+ unsubscribe: jest.fn(),
39
+ MessageContext: jest.fn()
40
+ }),
41
+ { virtual: true }
42
42
  );`);
43
43
  }
44
44
  // Analyze wire/data patterns
45
45
  if (transformedMarkup.recordDataServices.length > 0) {
46
46
  imports.push("import { getRecord, getFieldValue } from 'lightning/uiRecordApi';");
47
47
  // Mock wire adapter
48
- mocks.push(`// Mock getRecord wire adapter
48
+ mocks.push(`// Mock getRecord wire adapter
49
49
  const mockGetRecord = require('lightning/uiRecordApi').getRecord;`);
50
50
  for (const rds of transformedMarkup.recordDataServices) {
51
51
  behaviorSpecs.push({
@@ -66,11 +66,11 @@ const mockGetRecord = require('lightning/uiRecordApi').getRecord;`);
66
66
  initApexMethod = initFunc.serverCalls[0].controllerMethod || null;
67
67
  if (initApexMethod) {
68
68
  imports.push(`import ${initApexMethod} from '@salesforce/apex/${markup.controller}.${initApexMethod}';`);
69
- mocks.push(`// Mock Apex method
70
- jest.mock(
71
- '@salesforce/apex/${markup.controller}.${initApexMethod}',
72
- () => ({ default: jest.fn() }),
73
- { virtual: true }
69
+ mocks.push(`// Mock Apex method
70
+ jest.mock(
71
+ '@salesforce/apex/${markup.controller}.${initApexMethod}',
72
+ () => ({ default: jest.fn() }),
73
+ { virtual: true }
74
74
  );`);
75
75
  behaviorSpecs.push({
76
76
  category: 'data',
@@ -82,33 +82,33 @@ jest.mock(
82
82
  }
83
83
  }
84
84
  // Generate test structure
85
- let testContent = `/**
86
- * Jest tests for ${lwcName}
87
- * Converted from Aura component: ${markup.componentName}
88
- *
89
- * These tests verify that the converted LWC preserves the original behaviors.
90
- */
91
-
92
- ${imports.join('\n')}
93
-
94
- ${mocks.join('\n\n')}
95
-
96
- describe('${lwcName}', () => {
97
- let element;
98
-
99
- beforeEach(() => {
100
- element = createElement('c-${lwcName}', {
101
- is: ${className}
102
- });
103
- });
104
-
105
- afterEach(() => {
106
- while (document.body.firstChild) {
107
- document.body.removeChild(document.body.firstChild);
108
- }
109
- jest.clearAllMocks();
110
- });
111
-
85
+ let testContent = `/**
86
+ * Jest tests for ${lwcName}
87
+ * Converted from Aura component: ${markup.componentName}
88
+ *
89
+ * These tests verify that the converted LWC preserves the original behaviors.
90
+ */
91
+
92
+ ${imports.join('\n')}
93
+
94
+ ${mocks.join('\n\n')}
95
+
96
+ describe('${lwcName}', () => {
97
+ let element;
98
+
99
+ beforeEach(() => {
100
+ element = createElement('c-${lwcName}', {
101
+ is: ${className}
102
+ });
103
+ });
104
+
105
+ afterEach(() => {
106
+ while (document.body.firstChild) {
107
+ document.body.removeChild(document.body.firstChild);
108
+ }
109
+ jest.clearAllMocks();
110
+ });
111
+
112
112
  `;
113
113
  // Generate LMS Subscriber tests
114
114
  if (hasLmsSubscriber) {
@@ -126,67 +126,67 @@ describe('${lwcName}', () => {
126
126
  auraPattern: 'Automatic cleanup by Aura framework',
127
127
  lwcEquivalent: `unsubscribe(subscription) in disconnectedCallback`
128
128
  });
129
- testContent += ` /**
130
- * LMS Subscription Tests
131
- * Original Aura: lightning:messageChannel type="${lms.channelName}" onMessage="{!c.${lms.onMessageHandler}}"
132
- */
133
- describe('LMS Subscription - ${lms.channelName}', () => {
134
- test('should subscribe to message channel on connect', () => {
135
- // Arrange & Act
136
- document.body.appendChild(element);
137
-
138
- // Assert
139
- expect(subscribe).toHaveBeenCalledWith(
140
- expect.anything(), // MessageContext
141
- ${channelVar},
142
- expect.any(Function)
143
- );
144
- });
145
-
146
- test('should unsubscribe from message channel on disconnect', () => {
147
- // Arrange
148
- document.body.appendChild(element);
149
-
150
- // Act
151
- document.body.removeChild(element);
152
-
153
- // Assert
154
- expect(unsubscribe).toHaveBeenCalled();
155
- });
156
-
157
- test('should handle incoming message and update state', async () => {
158
- // Arrange
159
- document.body.appendChild(element);
160
- const mockRecordId = '003xx000004TtgAAC';
161
-
162
- // Get the message handler that was registered
163
- const messageHandler = subscribe.mock.calls[0][2];
164
-
165
- // Act - simulate receiving a message
166
- messageHandler({ recordId: mockRecordId });
167
-
168
- // Wait for reactivity
169
- await Promise.resolve();
170
-
171
- // Assert - verify state was updated
172
- // The original Aura set v.contactId from message.getParam('recordId')
173
- expect(element.contactId).toBe(mockRecordId);
174
- });
175
-
176
- test('should clear state when message has no recordId', async () => {
177
- // Arrange
178
- document.body.appendChild(element);
179
- const messageHandler = subscribe.mock.calls[0][2];
180
-
181
- // Act - simulate receiving empty message
182
- messageHandler({});
183
- await Promise.resolve();
184
-
185
- // Assert
186
- expect(element.contactId).toBe('');
187
- });
188
- });
189
-
129
+ testContent += ` /**
130
+ * LMS Subscription Tests
131
+ * Original Aura: lightning:messageChannel type="${lms.channelName}" onMessage="{!c.${lms.onMessageHandler}}"
132
+ */
133
+ describe('LMS Subscription - ${lms.channelName}', () => {
134
+ test('should subscribe to message channel on connect', () => {
135
+ // Arrange & Act
136
+ document.body.appendChild(element);
137
+
138
+ // Assert
139
+ expect(subscribe).toHaveBeenCalledWith(
140
+ expect.anything(), // MessageContext
141
+ ${channelVar},
142
+ expect.any(Function)
143
+ );
144
+ });
145
+
146
+ test('should unsubscribe from message channel on disconnect', () => {
147
+ // Arrange
148
+ document.body.appendChild(element);
149
+
150
+ // Act
151
+ document.body.removeChild(element);
152
+
153
+ // Assert
154
+ expect(unsubscribe).toHaveBeenCalled();
155
+ });
156
+
157
+ test('should handle incoming message and update state', async () => {
158
+ // Arrange
159
+ document.body.appendChild(element);
160
+ const mockRecordId = '003xx000004TtgAAC';
161
+
162
+ // Get the message handler that was registered
163
+ const messageHandler = subscribe.mock.calls[0][2];
164
+
165
+ // Act - simulate receiving a message
166
+ messageHandler({ recordId: mockRecordId });
167
+
168
+ // Wait for reactivity
169
+ await Promise.resolve();
170
+
171
+ // Assert - verify state was updated
172
+ // The original Aura set v.contactId from message.getParam('recordId')
173
+ expect(element.contactId).toBe(mockRecordId);
174
+ });
175
+
176
+ test('should clear state when message has no recordId', async () => {
177
+ // Arrange
178
+ document.body.appendChild(element);
179
+ const messageHandler = subscribe.mock.calls[0][2];
180
+
181
+ // Act - simulate receiving empty message
182
+ messageHandler({});
183
+ await Promise.resolve();
184
+
185
+ // Assert
186
+ expect(element.contactId).toBe('');
187
+ });
188
+ });
189
+
190
190
  `;
191
191
  }
192
192
  }
@@ -200,148 +200,148 @@ describe('${lwcName}', () => {
200
200
  auraPattern: `component.find('recordSelected').publish(payload)`,
201
201
  lwcEquivalent: `publish(messageContext, ${channelVar}, message)`
202
202
  });
203
- testContent += ` /**
204
- * LMS Publisher Tests
205
- * Original Aura: component.find('recordSelected').publish(payload)
206
- */
207
- describe('LMS Publishing - ${lms.channelName}', () => {
208
- test('should not subscribe to message channel (publisher only)', () => {
209
- // Arrange & Act
210
- document.body.appendChild(element);
211
-
212
- // Assert - publisher should NOT subscribe
213
- expect(subscribe).not.toHaveBeenCalled();
214
- });
215
-
216
- test('should publish message when publishMessage is called', async () => {
217
- // Arrange
218
- document.body.appendChild(element);
219
- const mockRecordId = '003xx000004TtgAAC';
220
-
221
- // Act
222
- element.publishMessage({ recordId: mockRecordId });
223
-
224
- // Assert
225
- expect(publish).toHaveBeenCalledWith(
226
- expect.anything(), // MessageContext
227
- ${channelVar},
228
- expect.objectContaining({ recordId: mockRecordId })
229
- );
230
- });
231
- });
232
-
203
+ testContent += ` /**
204
+ * LMS Publisher Tests
205
+ * Original Aura: component.find('recordSelected').publish(payload)
206
+ */
207
+ describe('LMS Publishing - ${lms.channelName}', () => {
208
+ test('should not subscribe to message channel (publisher only)', () => {
209
+ // Arrange & Act
210
+ document.body.appendChild(element);
211
+
212
+ // Assert - publisher should NOT subscribe
213
+ expect(subscribe).not.toHaveBeenCalled();
214
+ });
215
+
216
+ test('should publish message when publishMessage is called', async () => {
217
+ // Arrange
218
+ document.body.appendChild(element);
219
+ const mockRecordId = '003xx000004TtgAAC';
220
+
221
+ // Act
222
+ element.publishMessage({ recordId: mockRecordId });
223
+
224
+ // Assert
225
+ expect(publish).toHaveBeenCalledWith(
226
+ expect.anything(), // MessageContext
227
+ ${channelVar},
228
+ expect.objectContaining({ recordId: mockRecordId })
229
+ );
230
+ });
231
+ });
232
+
233
233
  `;
234
234
  }
235
235
  }
236
236
  // Generate Wire/Data tests
237
237
  if (transformedMarkup.recordDataServices.length > 0) {
238
- testContent += ` /**
239
- * Wire Adapter Tests (force:recordData equivalent)
240
- * Original Aura: force:recordData with reactive recordId binding
241
- */
242
- describe('Record Data Loading', () => {
238
+ testContent += ` /**
239
+ * Wire Adapter Tests (force:recordData equivalent)
240
+ * Original Aura: force:recordData with reactive recordId binding
241
+ */
242
+ describe('Record Data Loading', () => {
243
243
  `;
244
244
  for (const rds of transformedMarkup.recordDataServices) {
245
245
  const targetProp = rds.targetFields || 'record';
246
- testContent += ` test('should wire ${targetProp} with reactive ${rds.recordIdBinding}', async () => {
247
- // This test verifies the @wire decorator is properly configured
248
- // In Aura: force:recordData recordId="{!v.${rds.recordIdBinding}}" targetFields="{!v.${targetProp}}"
249
- // In LWC: @wire(getRecord, { recordId: '$${rds.recordIdBinding}', fields: [...] }) ${targetProp};
250
-
251
- // Arrange
252
- const mockRecord = {
253
- data: {
254
- fields: {
255
- ${rds.fields.map(f => ` ${f}: { value: 'Test ${f}' }`).join(',\n')}
256
- }
257
- }
258
- };
259
-
260
- // Act
261
- document.body.appendChild(element);
262
-
263
- // Simulate wire returning data
264
- // Note: In actual test, you'd use @salesforce/sfdx-lwc-jest wire adapter mocking
265
-
266
- // Assert structure exists
267
- expect(element).toBeDefined();
268
- });
269
-
246
+ testContent += ` test('should wire ${targetProp} with reactive ${rds.recordIdBinding}', async () => {
247
+ // This test verifies the @wire decorator is properly configured
248
+ // In Aura: force:recordData recordId="{!v.${rds.recordIdBinding}}" targetFields="{!v.${targetProp}}"
249
+ // In LWC: @wire(getRecord, { recordId: '$${rds.recordIdBinding}', fields: [...] }) ${targetProp};
250
+
251
+ // Arrange
252
+ const mockRecord = {
253
+ data: {
254
+ fields: {
255
+ ${rds.fields.map(f => ` ${f}: { value: 'Test ${f}' }`).join(',\n')}
256
+ }
257
+ }
258
+ };
259
+
260
+ // Act
261
+ document.body.appendChild(element);
262
+
263
+ // Simulate wire returning data
264
+ // Note: In actual test, you'd use @salesforce/sfdx-lwc-jest wire adapter mocking
265
+
266
+ // Assert structure exists
267
+ expect(element).toBeDefined();
268
+ });
269
+
270
270
  `;
271
271
  // Generate getter tests for each field
272
272
  for (const field of rds.fields) {
273
273
  const getterName = field.charAt(0).toLowerCase() + field.slice(1).replace(/__c$/i, '');
274
- testContent += ` test('getter ${getterName} should return undefined when no data', () => {
275
- // Original Aura: {!v.${targetProp}.${field}}
276
- // Converted LWC: {${getterName}} via getter using getFieldValue
277
-
278
- document.body.appendChild(element);
279
- expect(element.${getterName}).toBeUndefined();
280
- });
281
-
274
+ testContent += ` test('getter ${getterName} should return undefined when no data', () => {
275
+ // Original Aura: {!v.${targetProp}.${field}}
276
+ // Converted LWC: {${getterName}} via getter using getFieldValue
277
+
278
+ document.body.appendChild(element);
279
+ expect(element.${getterName}).toBeUndefined();
280
+ });
281
+
282
282
  `;
283
283
  }
284
284
  }
285
- testContent += ` });
286
-
285
+ testContent += ` });
286
+
287
287
  `;
288
288
  }
289
289
  // Generate init/Apex wire tests
290
290
  if (initApexMethod) {
291
- testContent += ` /**
292
- * Init/Data Loading Tests
293
- * Original Aura: aura:handler name="init" calling ${initApexMethod}
294
- * Converted LWC: @wire(${initApexMethod})
295
- */
296
- describe('Initial Data Loading', () => {
297
- test('should wire ${initApexMethod} for automatic data loading', () => {
298
- // In Aura: doInit called $A.enqueueAction for ${initApexMethod}
299
- // In LWC: @wire(${initApexMethod}) loads data declaratively
300
-
301
- document.body.appendChild(element);
302
-
303
- // With @wire, data loads automatically - no imperative call needed
304
- // The test verifies the wire adapter is properly configured
305
- expect(element).toBeDefined();
306
- });
307
- });
308
-
291
+ testContent += ` /**
292
+ * Init/Data Loading Tests
293
+ * Original Aura: aura:handler name="init" calling ${initApexMethod}
294
+ * Converted LWC: @wire(${initApexMethod})
295
+ */
296
+ describe('Initial Data Loading', () => {
297
+ test('should wire ${initApexMethod} for automatic data loading', () => {
298
+ // In Aura: doInit called $A.enqueueAction for ${initApexMethod}
299
+ // In LWC: @wire(${initApexMethod}) loads data declaratively
300
+
301
+ document.body.appendChild(element);
302
+
303
+ // With @wire, data loads automatically - no imperative call needed
304
+ // The test verifies the wire adapter is properly configured
305
+ expect(element).toBeDefined();
306
+ });
307
+ });
308
+
309
309
  `;
310
310
  }
311
311
  // Generate UI rendering tests
312
- testContent += ` /**
313
- * UI Rendering Tests
314
- * Verify template renders correctly with data
315
- */
316
- describe('UI Rendering', () => {
317
- test('should render component', () => {
318
- document.body.appendChild(element);
319
- expect(element).toBeTruthy();
320
- });
321
-
322
- test('should render lightning-card with correct title', () => {
323
- document.body.appendChild(element);
324
- const card = element.shadowRoot.querySelector('lightning-card');
325
- expect(card).toBeTruthy();
326
- expect(card.title).toBe('${markup.componentName}');
327
- });
312
+ testContent += ` /**
313
+ * UI Rendering Tests
314
+ * Verify template renders correctly with data
315
+ */
316
+ describe('UI Rendering', () => {
317
+ test('should render component', () => {
318
+ document.body.appendChild(element);
319
+ expect(element).toBeTruthy();
320
+ });
321
+
322
+ test('should render lightning-card with correct title', () => {
323
+ document.body.appendChild(element);
324
+ const card = element.shadowRoot.querySelector('lightning-card');
325
+ expect(card).toBeTruthy();
326
+ expect(card.title).toBe('${markup.componentName}');
327
+ });
328
328
  `;
329
329
  // Add conditional rendering tests if aura:if was present
330
330
  if (markup.body.some(node => node.name === 'aura:if')) {
331
- testContent += `
332
- test('should conditionally render content', async () => {
333
- // Original Aura: <aura:if isTrue="{!v.someCondition}">
334
- // Converted LWC: <template if:true={someCondition}>
335
-
336
- document.body.appendChild(element);
337
-
338
- // Initially should not show conditional content
339
- // After data loads, should show content
340
- });
331
+ testContent += `
332
+ test('should conditionally render content', async () => {
333
+ // Original Aura: <aura:if isTrue="{!v.someCondition}">
334
+ // Converted LWC: <template if:true={someCondition}>
335
+
336
+ document.body.appendChild(element);
337
+
338
+ // Initially should not show conditional content
339
+ // After data loads, should show content
340
+ });
341
341
  `;
342
342
  }
343
- testContent += ` });
344
- });
343
+ testContent += ` });
344
+ });
345
345
  `;
346
346
  return {
347
347
  filename: `${lwcName}.test.js`,
@@ -354,22 +354,22 @@ ${rds.fields.map(f => ` ${f}: { value: 'Test ${f}' }`).jo
354
354
  */
355
355
  function generateBehaviorSpecDocument(componentName, specs) {
356
356
  const lwcName = (0, file_io_1.toLwcName)(componentName);
357
- let doc = `# Behavior Specification: ${componentName} → ${lwcName}
358
-
359
- This document maps the expected behaviors from the original Aura component to their LWC equivalents.
360
- Use this as a checklist to verify the conversion is correct.
361
-
362
- ## Behavior Mapping
363
-
364
- | Category | Behavior | Aura Pattern | LWC Equivalent |
365
- |----------|----------|--------------|----------------|
357
+ let doc = `# Behavior Specification: ${componentName} → ${lwcName}
358
+
359
+ This document maps the expected behaviors from the original Aura component to their LWC equivalents.
360
+ Use this as a checklist to verify the conversion is correct.
361
+
362
+ ## Behavior Mapping
363
+
364
+ | Category | Behavior | Aura Pattern | LWC Equivalent |
365
+ |----------|----------|--------------|----------------|
366
366
  `;
367
367
  for (const spec of specs) {
368
368
  doc += `| ${spec.category} | ${spec.description} | \`${spec.auraPattern}\` | \`${spec.lwcEquivalent}\` |\n`;
369
369
  }
370
- doc += `
371
- ## Test Checklist
372
-
370
+ doc += `
371
+ ## Test Checklist
372
+
373
373
  `;
374
374
  const categories = [...new Set(specs.map(s => s.category))];
375
375
  for (const cat of categories) {
package/dist/index.js CHANGED
@@ -55,6 +55,7 @@ program
55
55
  .option('--full', 'Run full automated conversion (default: scaffolding only)', false)
56
56
  .option('-o, --output <dir>', 'Output directory', options_1.DEFAULT_OUTPUT_DIR)
57
57
  .option('--open', 'Open output folder in file explorer after conversion', false)
58
+ .option('--preview', 'Generate and open HTML preview of converted component', false)
58
59
  .option('--dry-run', 'Preview conversion without writing files', false)
59
60
  .option('--verbose', 'Show detailed conversion logs', false)
60
61
  .action(async (bundlePath, options) => {
@@ -65,6 +66,7 @@ program
65
66
  dryRun: options.dryRun,
66
67
  verbose: options.verbose,
67
68
  open: options.open,
69
+ preview: options.preview,
68
70
  });
69
71
  });
70
72
  // Visualforce conversion command
@@ -75,6 +77,7 @@ program
75
77
  .option('-o, --output <dir>', 'Output directory', options_1.DEFAULT_OUTPUT_DIR)
76
78
  .option('--controller <path>', 'Include Apex controller file for analysis')
77
79
  .option('--open', 'Open output folder in file explorer after conversion', false)
80
+ .option('--preview', 'Generate and open HTML preview of converted component', false)
78
81
  .option('--dry-run', 'Preview conversion without writing files', false)
79
82
  .option('--verbose', 'Show detailed conversion logs', false)
80
83
  .action(async (pagePath, options) => {
@@ -86,6 +89,7 @@ program
86
89
  verbose: options.verbose,
87
90
  controller: options.controller,
88
91
  open: options.open,
92
+ preview: options.preview,
89
93
  });
90
94
  });
91
95
  // Session management command
@@ -150,41 +154,49 @@ program
150
154
  }
151
155
  });
152
156
  // Examples in help
153
- program.addHelpText('after', `
154
- Examples:
155
- # Convert Aura component (just use the name!)
156
- $ ${options_1.CLI_NAME} aura AccountCard
157
- $ ${options_1.CLI_NAME} aura AccountCard --full
158
-
159
- # Convert Visualforce page (just use the name!)
160
- $ ${options_1.CLI_NAME} vf ContactList
161
- $ ${options_1.CLI_NAME} vf ContactList --controller ContactListController
162
-
163
- # Full paths also work
164
- $ ${options_1.CLI_NAME} aura ./force-app/main/default/aura/MyComponent
165
- $ ${options_1.CLI_NAME} vf ./pages/MyPage.page --controller ./classes/MyController.cls
166
-
167
- # Preview without writing files
168
- $ ${options_1.CLI_NAME} aura MyComponent --dry-run --verbose
169
-
170
- # Specify output directory
171
- $ ${options_1.CLI_NAME} vf ContactList -o ./src/lwc
172
-
173
- # View session data and learned patterns
174
- $ ${options_1.CLI_NAME} session
175
- $ ${options_1.CLI_NAME} session --report
176
- $ ${options_1.CLI_NAME} session --patterns
177
-
178
- Smart Path Resolution:
179
- The CLI searches common Salesforce project locations automatically:
180
- - Aura: force-app/main/default/aura/, src/aura/, aura/
181
- - VF: force-app/main/default/pages/, src/pages/, pages/
182
- - Apex: force-app/main/default/classes/, src/classes/, classes/
183
-
184
- Session Management:
185
- Conversion data is stored in a temp folder during your session.
186
- This helps the tool learn from patterns and provide better suggestions.
187
- Use 'session --report' to see full session statistics.
157
+ program.addHelpText('after', `
158
+ Examples:
159
+ # Convert Aura component (just use the name!)
160
+ $ ${options_1.CLI_NAME} aura AccountCard
161
+ $ ${options_1.CLI_NAME} aura AccountCard --full
162
+
163
+ # Convert Visualforce page (just use the name!)
164
+ $ ${options_1.CLI_NAME} vf ContactList
165
+ $ ${options_1.CLI_NAME} vf ContactList --controller ContactListController
166
+
167
+ # Full paths also work
168
+ $ ${options_1.CLI_NAME} aura ./force-app/main/default/aura/MyComponent
169
+ $ ${options_1.CLI_NAME} vf ./pages/MyPage.page --controller ./classes/MyController.cls
170
+
171
+ # Preview the converted UI in your browser
172
+ $ ${options_1.CLI_NAME} aura MyComponent --preview
173
+ $ ${options_1.CLI_NAME} vf ContactList --preview --full
174
+
175
+ # Preview without writing files
176
+ $ ${options_1.CLI_NAME} aura MyComponent --dry-run --verbose
177
+
178
+ # Specify output directory
179
+ $ ${options_1.CLI_NAME} vf ContactList -o ./src/lwc
180
+
181
+ # View session data and learned patterns
182
+ $ ${options_1.CLI_NAME} session
183
+ $ ${options_1.CLI_NAME} session --report
184
+ $ ${options_1.CLI_NAME} session --patterns
185
+
186
+ Smart Path Resolution:
187
+ The CLI searches common Salesforce project locations automatically:
188
+ - Aura: force-app/main/default/aura/, src/aura/, aura/
189
+ - VF: force-app/main/default/pages/, src/pages/, pages/
190
+ - Apex: force-app/main/default/classes/, src/classes/, classes/
191
+
192
+ UI Preview:
193
+ Use --preview to generate a standalone HTML file that shows how your
194
+ converted LWC will look using SLDS styling. Opens in your default browser.
195
+
196
+ Session Management:
197
+ Conversion data is stored in a temp folder during your session.
198
+ This helps the tool learn from patterns and provide better suggestions.
199
+ Use 'session --report' to see full session statistics.
188
200
  `);
189
201
  // Parse and execute
190
202
  // If no arguments provided, launch interactive TUI
@@ -202,6 +214,7 @@ if (process.argv.slice(2).length === 0) {
202
214
  dryRun: false,
203
215
  verbose: false,
204
216
  open: answers.openFolder,
217
+ preview: answers.preview,
205
218
  });
206
219
  }
207
220
  else {
@@ -212,6 +225,7 @@ if (process.argv.slice(2).length === 0) {
212
225
  verbose: false,
213
226
  controller: answers.controllerPath,
214
227
  open: answers.openFolder,
228
+ preview: answers.preview,
215
229
  });
216
230
  }
217
231
  }