gbu-accessibility-package 3.8.8 → 3.9.0

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/cli.js CHANGED
@@ -124,6 +124,11 @@ for (let i = 0; i < args.length; i++) {
124
124
  case '--missing-resources':
125
125
  options.missingResourcesOnly = true;
126
126
  break;
127
+ case '--gtm-check':
128
+ case '--check-gtm':
129
+ case '--google-tag-manager':
130
+ options.gtmCheckOnly = true;
131
+ break;
127
132
  case '--unused-files':
128
133
  options.unusedFilesOnly = true;
129
134
  break;
@@ -192,6 +197,7 @@ Options:
192
197
  --links-check Check for broken links and 404 resources (no auto-fix)
193
198
  --broken-links Check for broken external links only (no auto-fix)
194
199
  --404-resources Check for missing local resources only (no auto-fix)
200
+ --gtm-check Check Google Tag Manager installation (no auto-fix)
195
201
  --unused-files Check for unused files in project (no auto-fix)
196
202
  --dead-code Check for dead code in CSS and JavaScript (no auto-fix)
197
203
  --file-size, --size-check Check file sizes and suggest optimizations (no auto-fix)
@@ -228,6 +234,7 @@ Examples:
228
234
  node cli.js --links-check # Check for broken links and 404s
229
235
  node cli.js --broken-links # Check for broken external links only
230
236
  node cli.js --404-resources # Check for missing local resources only
237
+ node cli.js --gtm-check # Check Google Tag Manager installation
231
238
  node cli.js --unused-files # Check for unused files in project
232
239
  node cli.js --dead-code # Check for dead CSS and JavaScript code
233
240
  node cli.js --file-size # Check file sizes and suggest optimizations
@@ -252,28 +259,28 @@ Features:
252
259
 
253
260
 
254
261
  // Helper function to show completion message with backup info
255
- function showCompletionMessage(options, mode = 'fixes') {
262
+ function showCompletionMessage(options, mode = 'sửa lỗi') {
256
263
  if (options.dryRun) {
257
- console.log(chalk.cyan('\n💡 This was a dry run. Use without --dry-run to apply changes.'));
264
+ console.log(chalk.cyan('\n💡 Đây chế độ xem trước. Sử dụng không có --dry-run để áp dụng thay đổi.'));
258
265
  } else {
259
- console.log(chalk.green(`\n🎉 ${mode} completed successfully!`));
266
+ console.log(chalk.green(`\n🎉 ${mode} hoàn tất thành công!`));
260
267
  if (options.backupFiles) {
261
- console.log(chalk.gray(' 📁 Backup files created with .backup extension'));
262
- console.log(chalk.gray(' 💡 Use --no-backup to disable backups in future runs'));
268
+ console.log(chalk.gray(' 📁 Đã tạo file backup với đuôi .backup'));
269
+ console.log(chalk.gray(' 💡 Sử dụng --no-backup để tắt backup trong các lần chạy sau'));
263
270
  } else {
264
- console.log(chalk.blue(' ⚡ No backup files created (default behavior for faster processing)'));
265
- console.log(chalk.gray(' 💡 Use --backup to enable backups for safety'));
271
+ console.log(chalk.blue(' ⚡ Không tạo file backup (mặc định để xử lý nhanh hơn)'));
272
+ console.log(chalk.gray(' 💡 Sử dụng --backup để bật tính năng backup để an toàn'));
266
273
  }
267
274
  }
268
275
  }
269
276
 
270
277
  // Main function
271
278
  async function main() {
272
- console.log(chalk.blue('🚀 Starting Accessibility Fixer...'));
273
- console.log(chalk.gray(`Directory: ${path.resolve(options.directory)}`));
274
- console.log(chalk.gray(`Language: ${options.language}`));
275
- console.log(chalk.gray(`Backup: ${options.backupFiles ? 'Yes' : 'No'}`));
276
- console.log(chalk.gray(`Mode: ${options.dryRun ? 'Dry Run (Preview)' : 'Apply Changes'}`));
279
+ console.log(chalk.blue('🚀 Đang khởi động Accessibility Fixer...'));
280
+ console.log(chalk.gray(`Thư mục: ${path.resolve(options.directory)}`));
281
+ console.log(chalk.gray(`Ngôn ngữ: ${options.language}`));
282
+ console.log(chalk.gray(`Backup: ${options.backupFiles ? '' : 'Không'}`));
283
+ console.log(chalk.gray(`Chế độ: ${options.dryRun ? 'Xem trước (Preview)' : 'Áp dụng thay đổi'}`));
277
284
  console.log('');
278
285
 
279
286
  const fixer = new AccessibilityFixer({
@@ -292,11 +299,11 @@ async function main() {
292
299
  // Handle different modes - All modes now include cleanup
293
300
  if (options.cleanupOnly || options.altOnly || options.langOnly || options.roleOnly || options.ariaLabelOnly ||
294
301
  options.formsOnly || options.nestedOnly || options.buttonsOnly || options.linksOnly || options.landmarksOnly ||
295
- options.headingsOnly || options.dlOnly || options.linksCheckOnly || options.brokenLinksOnly || options.missingResourcesOnly || options.unusedFilesOnly || options.deadCodeOnly || options.fileSizeOnly) {
302
+ options.headingsOnly || options.dlOnly || options.linksCheckOnly || options.brokenLinksOnly || options.missingResourcesOnly || options.gtmCheckOnly || options.unusedFilesOnly || options.deadCodeOnly || options.fileSizeOnly) {
296
303
  // Individual modes - handle each separately, then run cleanup
297
304
  } else {
298
305
  // Default mode: Run comprehensive fix (all fixes including cleanup)
299
- console.log(chalk.blue('🎯 Running comprehensive accessibility fixes...'));
306
+ console.log(chalk.blue('🎯 Đang chạy sửa lỗi accessibility toàn diện...'));
300
307
  const results = await fixer.fixAllAccessibilityIssues(options.directory);
301
308
 
302
309
  // Results already logged in the method
@@ -306,312 +313,328 @@ async function main() {
306
313
  // Individual modes
307
314
  if (options.cleanupOnly) {
308
315
  // Only cleanup duplicate roles
309
- console.log(chalk.blue('🧹 Running cleanup for duplicate role attributes...'));
316
+ console.log(chalk.blue('🧹 Đang dọn dẹp các thuộc tính role trùng lặp...'));
310
317
  const cleanupResults = await fixer.cleanupDuplicateRoles(options.directory);
311
318
  const cleanupFixed = cleanupResults.filter(r => r.status === 'fixed').length;
312
319
 
313
- console.log(chalk.green(`\n✅ Cleaned duplicate roles in ${cleanupFixed} files`));
320
+ console.log(chalk.green(`\n✅ Đã dọn dẹp role trùng lặp trong ${cleanupFixed} file`));
314
321
 
315
- showCompletionMessage(options, 'Cleanup');
322
+ showCompletionMessage(options, 'Dọn dẹp');
316
323
  return;
317
324
 
318
325
  } else if (options.cleanupOnly) {
319
326
  // Only cleanup duplicate roles
320
- console.log(chalk.blue('🧹 Running cleanup for duplicate role attributes...'));
327
+ console.log(chalk.blue('🧹 Đang dọn dẹp các thuộc tính role trùng lặp...'));
321
328
  const cleanupResults = await fixer.cleanupDuplicateRoles(options.directory);
322
329
  const cleanupFixed = cleanupResults.filter(r => r.status === 'fixed').length;
323
330
 
324
- console.log(chalk.green(`\n✅ Cleaned duplicate roles in ${cleanupFixed} files`));
331
+ console.log(chalk.green(`\n✅ Đã dọn dẹp role trùng lặp trong ${cleanupFixed} file`));
325
332
 
326
- showCompletionMessage(options, 'Cleanup');
333
+ showCompletionMessage(options, 'Dọn dẹp');
327
334
  return;
328
335
 
329
336
  } else if (options.altOnly) {
330
337
  // Fix alt attributes + cleanup
331
- console.log(chalk.blue('🖼️ Running alt attribute fixes + cleanup...'));
338
+ console.log(chalk.blue('🖼️ Đang sửa thuộc tính alt + dọn dẹp...'));
332
339
  const altResults = await fixer.fixEmptyAltAttributes(options.directory);
333
340
  const altFixed = altResults.filter(r => r.status === 'fixed').length;
334
341
  const totalAltIssues = altResults.reduce((sum, r) => sum + (r.issues || 0), 0);
335
342
 
336
- console.log(chalk.green(`\n✅ Fixed alt attributes in ${altFixed} files (${totalAltIssues} issues)`));
343
+ console.log(chalk.green(`\n✅ Đã sửa thuộc tính alt trong ${altFixed} file (${totalAltIssues} vấn đề)`));
337
344
 
338
345
  // Run cleanup
339
- console.log(chalk.blue('\n🧹 Running cleanup for duplicate role attributes...'));
346
+ console.log(chalk.blue('\n🧹 Đang dọn dẹp các thuộc tính role trùng lặp...'));
340
347
  const cleanupResults = await fixer.cleanupDuplicateRoles(options.directory);
341
348
  const cleanupFixed = cleanupResults.filter(r => r.status === 'fixed').length;
342
- console.log(chalk.green(`✅ Cleaned duplicate roles in ${cleanupFixed} files`));
349
+ console.log(chalk.green(`✅ Đã dọn dẹp role trùng lặp trong ${cleanupFixed} file`));
343
350
 
344
- showCompletionMessage(options, 'Alt attribute fixes + cleanup');
351
+ showCompletionMessage(options, 'Sửa thuộc tính alt + dọn dẹp');
345
352
  return;
346
353
 
347
354
  } else if (options.langOnly) {
348
355
  // Fix lang attributes + cleanup
349
- console.log(chalk.blue('📝 Running HTML lang attribute fixes + cleanup...'));
356
+ console.log(chalk.blue('📝 Đang sửa thuộc tính HTML lang + dọn dẹp...'));
350
357
  const langResults = await fixer.fixHtmlLang(options.directory);
351
358
  const langFixed = langResults.filter(r => r.status === 'fixed').length;
352
359
 
353
- console.log(chalk.green(`\n✅ Fixed lang attributes in ${langFixed} files`));
360
+ console.log(chalk.green(`\n✅ Đã sửa thuộc tính lang trong ${langFixed} file`));
354
361
 
355
362
  // Run cleanup
356
- console.log(chalk.blue('\n🧹 Running cleanup for duplicate role attributes...'));
363
+ console.log(chalk.blue('\n🧹 Đang dọn dẹp các thuộc tính role trùng lặp...'));
357
364
  const cleanupResults = await fixer.cleanupDuplicateRoles(options.directory);
358
365
  const cleanupFixed = cleanupResults.filter(r => r.status === 'fixed').length;
359
- console.log(chalk.green(`✅ Cleaned duplicate roles in ${cleanupFixed} files`));
366
+ console.log(chalk.green(`✅ Đã dọn dẹp role trùng lặp trong ${cleanupFixed} file`));
360
367
 
361
- showCompletionMessage(options, 'Lang attribute fixes + cleanup');
368
+ showCompletionMessage(options, 'Sửa thuộc tính lang + dọn dẹp');
362
369
  return;
363
370
 
364
371
  } else if (options.roleOnly) {
365
372
  // Fix role attributes + cleanup
366
- console.log(chalk.blue('🎭 Running role attribute fixes + cleanup...'));
373
+ console.log(chalk.blue('🎭 Đang sửa thuộc tính role + dọn dẹp...'));
367
374
  const roleResults = await fixer.fixRoleAttributes(options.directory);
368
375
  const roleFixed = roleResults.filter(r => r.status === 'fixed').length;
369
376
  const totalRoleIssues = roleResults.reduce((sum, r) => sum + (r.issues || 0), 0);
370
377
 
371
- console.log(chalk.green(`\n✅ Fixed role attributes in ${roleFixed} files (${totalRoleIssues} issues)`));
378
+ console.log(chalk.green(`\n✅ Đã sửa thuộc tính role trong ${roleFixed} file (${totalRoleIssues} vấn đề)`));
372
379
 
373
380
  // Run cleanup
374
- console.log(chalk.blue('\n🧹 Running cleanup for duplicate role attributes...'));
381
+ console.log(chalk.blue('\n🧹 Đang dọn dẹp các thuộc tính role trùng lặp...'));
375
382
  const cleanupResults = await fixer.cleanupDuplicateRoles(options.directory);
376
383
  const cleanupFixed = cleanupResults.filter(r => r.status === 'fixed').length;
377
- console.log(chalk.green(`✅ Cleaned duplicate roles in ${cleanupFixed} files`));
384
+ console.log(chalk.green(`✅ Đã dọn dẹp role trùng lặp trong ${cleanupFixed} file`));
378
385
 
379
- showCompletionMessage(options, 'Role attribute fixes + cleanup');
386
+ showCompletionMessage(options, 'Sửa thuộc tính role + dọn dẹp');
380
387
  return;
381
388
 
382
389
  } else if (options.ariaLabelOnly) {
383
390
  // Fix aria-label attributes + cleanup
384
- console.log(chalk.blue('🏷️ Running aria-label attribute fixes + cleanup...'));
391
+ console.log(chalk.blue('🏷️ Đang sửa thuộc tính aria-label + dọn dẹp...'));
385
392
  const ariaResults = await fixer.fixAriaLabels(options.directory);
386
393
  const ariaFixed = ariaResults.filter(r => r.status === 'processed' && r.changes > 0).length;
387
394
  const totalAriaIssues = ariaResults.reduce((sum, r) => sum + (r.changes || 0), 0);
388
395
 
389
- console.log(chalk.green(`\n✅ Fixed aria-label attributes in ${ariaFixed} files (${totalAriaIssues} issues)`));
396
+ console.log(chalk.green(`\n✅ Đã sửa thuộc tính aria-label trong ${ariaFixed} file (${totalAriaIssues} vấn đề)`));
390
397
 
391
398
  // Run cleanup
392
- console.log(chalk.blue('\n🧹 Running cleanup for duplicate role attributes...'));
399
+ console.log(chalk.blue('\n🧹 Đang dọn dẹp các thuộc tính role trùng lặp...'));
393
400
  const cleanupResults = await fixer.cleanupDuplicateRoles(options.directory);
394
401
  const cleanupFixed = cleanupResults.filter(r => r.status === 'fixed').length;
395
- console.log(chalk.green(`✅ Cleaned duplicate roles in ${cleanupFixed} files`));
402
+ console.log(chalk.green(`✅ Đã dọn dẹp role trùng lặp trong ${cleanupFixed} file`));
396
403
 
397
- showCompletionMessage(options, 'Aria-label attribute fixes + cleanup');
404
+ showCompletionMessage(options, 'Sửa thuộc tính aria-label + dọn dẹp');
398
405
  return;
399
406
 
400
407
  } else if (options.formsOnly) {
401
408
  // Fix form labels + cleanup
402
- console.log(chalk.blue('📋 Running form label fixes + cleanup...'));
409
+ console.log(chalk.blue('📋 Đang sửa nhãn form + dọn dẹp...'));
403
410
  const formResults = await fixer.fixFormLabels(options.directory);
404
411
  const formFixed = formResults.filter(r => r.status === 'fixed').length;
405
412
  const totalFormIssues = formResults.reduce((sum, r) => sum + (r.issues || 0), 0);
406
413
 
407
- console.log(chalk.green(`\n✅ Fixed form labels in ${formFixed} files (${totalFormIssues} issues)`));
414
+ console.log(chalk.green(`\n✅ Đã sửa nhãn form trong ${formFixed} file (${totalFormIssues} vấn đề)`));
408
415
 
409
416
  // Run cleanup
410
- console.log(chalk.blue('\n🧹 Running cleanup for duplicate role attributes...'));
417
+ console.log(chalk.blue('\n🧹 Đang dọn dẹp các thuộc tính role trùng lặp...'));
411
418
  const cleanupResults = await fixer.cleanupDuplicateRoles(options.directory);
412
419
  const cleanupFixed = cleanupResults.filter(r => r.status === 'fixed').length;
413
- console.log(chalk.green(`✅ Cleaned duplicate roles in ${cleanupFixed} files`));
420
+ console.log(chalk.green(`✅ Đã dọn dẹp role trùng lặp trong ${cleanupFixed} file`));
414
421
 
415
- showCompletionMessage(options, 'Form label fixes + cleanup');
422
+ showCompletionMessage(options, 'Sửa nhãn form + dọn dẹp');
416
423
  return;
417
424
 
418
425
  } else if (options.nestedOnly) {
419
426
  // Fix nested interactive controls + cleanup
420
- console.log(chalk.blue('🎯 Running nested interactive controls fixes + cleanup...'));
427
+ console.log(chalk.blue('🎯 Đang sửa các control tương tác lồng nhau + dọn dẹp...'));
421
428
  const nestedResults = await fixer.fixNestedInteractiveControls(options.directory);
422
429
  const nestedFixed = nestedResults.filter(r => r.status === 'fixed').length;
423
430
  const totalNestedIssues = nestedResults.reduce((sum, r) => sum + (r.issues || 0), 0);
424
431
 
425
- console.log(chalk.green(`\n✅ Fixed nested interactive controls in ${nestedFixed} files (${totalNestedIssues} issues)`));
432
+ console.log(chalk.green(`\n✅ Đã sửa các control tương tác lồng nhau trong ${nestedFixed} file (${totalNestedIssues} vấn đề)`));
426
433
 
427
434
  // Run cleanup
428
- console.log(chalk.blue('\n🧹 Running cleanup for duplicate role attributes...'));
435
+ console.log(chalk.blue('\n🧹 Đang dọn dẹp các thuộc tính role trùng lặp...'));
429
436
  const cleanupResults = await fixer.cleanupDuplicateRoles(options.directory);
430
437
  const cleanupFixed = cleanupResults.filter(r => r.status === 'fixed').length;
431
- console.log(chalk.green(`✅ Cleaned duplicate roles in ${cleanupFixed} files`));
438
+ console.log(chalk.green(`✅ Đã dọn dẹp role trùng lặp trong ${cleanupFixed} file`));
432
439
 
433
- showCompletionMessage(options, 'Nested interactive controls fixes + cleanup');
440
+ showCompletionMessage(options, 'Sửa các control tương tác lồng nhau + dọn dẹp');
434
441
  return;
435
442
 
436
443
  } else if (options.buttonsOnly) {
437
444
  // Fix button names + cleanup
438
- console.log(chalk.blue('🔘 Running button name fixes + cleanup...'));
445
+ console.log(chalk.blue('🔘 Đang sửa tên button + dọn dẹp...'));
439
446
  const buttonResults = await fixer.fixButtonNames(options.directory);
440
447
  const buttonFixed = buttonResults.filter(r => r.status === 'fixed').length;
441
448
  const totalButtonIssues = buttonResults.reduce((sum, r) => sum + (r.issues || 0), 0);
442
449
 
443
- console.log(chalk.green(`\n✅ Fixed button names in ${buttonFixed} files (${totalButtonIssues} issues)`));
450
+ console.log(chalk.green(`\n✅ Đã sửa tên button trong ${buttonFixed} file (${totalButtonIssues} vấn đề)`));
444
451
 
445
452
  // Run cleanup
446
- console.log(chalk.blue('\n🧹 Running cleanup for duplicate role attributes...'));
453
+ console.log(chalk.blue('\n🧹 Đang dọn dẹp các thuộc tính role trùng lặp...'));
447
454
  const cleanupResults = await fixer.cleanupDuplicateRoles(options.directory);
448
455
  const cleanupFixed = cleanupResults.filter(r => r.status === 'fixed').length;
449
- console.log(chalk.green(`✅ Cleaned duplicate roles in ${cleanupFixed} files`));
456
+ console.log(chalk.green(`✅ Đã dọn dẹp role trùng lặp trong ${cleanupFixed} file`));
450
457
 
451
- showCompletionMessage(options, 'Button name fixes + cleanup');
458
+ showCompletionMessage(options, 'Sửa tên button + dọn dẹp');
452
459
  return;
453
460
 
454
461
  } else if (options.linksOnly) {
455
462
  // Fix link names + cleanup
456
- console.log(chalk.blue('🔗 Running link name fixes + cleanup...'));
463
+ console.log(chalk.blue('🔗 Đang sửa tên link + dọn dẹp...'));
457
464
  const linkResults = await fixer.fixLinkNames(options.directory);
458
465
  const linkFixed = linkResults.filter(r => r.status === 'fixed').length;
459
466
  const totalLinkIssues = linkResults.reduce((sum, r) => sum + (r.issues || 0), 0);
460
467
 
461
- console.log(chalk.green(`\n✅ Fixed link names in ${linkFixed} files (${totalLinkIssues} issues)`));
468
+ console.log(chalk.green(`\n✅ Đã sửa tên link trong ${linkFixed} file (${totalLinkIssues} vấn đề)`));
462
469
 
463
470
  // Run cleanup
464
- console.log(chalk.blue('\n🧹 Running cleanup for duplicate role attributes...'));
471
+ console.log(chalk.blue('\n🧹 Đang dọn dẹp các thuộc tính role trùng lặp...'));
465
472
  const cleanupResults = await fixer.cleanupDuplicateRoles(options.directory);
466
473
  const cleanupFixed = cleanupResults.filter(r => r.status === 'fixed').length;
467
- console.log(chalk.green(`✅ Cleaned duplicate roles in ${cleanupFixed} files`));
474
+ console.log(chalk.green(`✅ Đã dọn dẹp role trùng lặp trong ${cleanupFixed} file`));
468
475
 
469
- showCompletionMessage(options, 'Link name fixes + cleanup');
476
+ showCompletionMessage(options, 'Sửa tên link + dọn dẹp');
470
477
  return;
471
478
 
472
479
  } else if (options.landmarksOnly) {
473
480
  // Fix landmarks + cleanup
474
- console.log(chalk.blue('🏛️ Running landmark fixes + cleanup...'));
481
+ console.log(chalk.blue('🏛️ Đang sửa landmark + dọn dẹp...'));
475
482
  const landmarkResults = await fixer.fixLandmarks(options.directory);
476
483
  const landmarkFixed = landmarkResults.filter(r => r.status === 'fixed').length;
477
484
  const totalLandmarkIssues = landmarkResults.reduce((sum, r) => sum + (r.issues || 0), 0);
478
485
 
479
- console.log(chalk.green(`\n✅ Fixed landmarks in ${landmarkFixed} files (${totalLandmarkIssues} issues)`));
486
+ console.log(chalk.green(`\n✅ Đã sửa landmark trong ${landmarkFixed} file (${totalLandmarkIssues} vấn đề)`));
480
487
 
481
488
  // Run cleanup
482
- console.log(chalk.blue('\n🧹 Running cleanup for duplicate role attributes...'));
489
+ console.log(chalk.blue('\n🧹 Đang dọn dẹp các thuộc tính role trùng lặp...'));
483
490
  const cleanupResults = await fixer.cleanupDuplicateRoles(options.directory);
484
491
  const cleanupFixed = cleanupResults.filter(r => r.status === 'fixed').length;
485
- console.log(chalk.green(`✅ Cleaned duplicate roles in ${cleanupFixed} files`));
492
+ console.log(chalk.green(`✅ Đã dọn dẹp role trùng lặp trong ${cleanupFixed} file`));
486
493
 
487
- showCompletionMessage(options, 'Landmark fixes + cleanup');
494
+ showCompletionMessage(options, 'Sửa landmark + dọn dẹp');
488
495
  return;
489
496
 
490
497
  } else if (options.headingsOnly) {
491
498
  // Fix heading structure + cleanup
492
- console.log(chalk.blue('📑 Running heading structure fixes + cleanup...'));
499
+ console.log(chalk.blue('📑 Đang sửa cấu trúc heading + dọn dẹp...'));
493
500
  const headingResults = await fixer.fixHeadingStructure(options.directory);
494
501
  const headingFixed = headingResults.filter(r => r.status === 'fixed').length;
495
502
  const totalHeadingIssues = headingResults.reduce((sum, r) => sum + (r.issues || 0), 0);
496
503
  const totalHeadingFixes = headingResults.reduce((sum, r) => sum + (r.fixes || 0), 0);
497
504
 
498
- console.log(chalk.green(`\n✅ Processed headings in ${headingResults.length} files (${totalHeadingIssues} issues found)`));
505
+ console.log(chalk.green(`\n✅ Đã xử heading trong ${headingResults.length} file (${totalHeadingIssues} vấn đề tìm thấy)`));
499
506
  if (options.autoFixHeadings) {
500
- console.log(chalk.green(`✅ Fixed ${totalHeadingFixes} heading issues automatically`));
507
+ console.log(chalk.green(`✅ Đã sửa ${totalHeadingFixes} vấn đề heading tự động`));
501
508
  } else {
502
- console.log(chalk.gray('💡 Use --auto-fix-headings to enable automatic heading fixes'));
509
+ console.log(chalk.gray('💡 Sử dụng --auto-fix-headings để bật tính năng tự động sửa heading'));
503
510
  }
504
511
 
505
512
  // Run cleanup
506
- console.log(chalk.blue('\n🧹 Running cleanup for duplicate role attributes...'));
513
+ console.log(chalk.blue('\n🧹 Đang dọn dẹp các thuộc tính role trùng lặp...'));
507
514
  const cleanupResults = await fixer.cleanupDuplicateRoles(options.directory);
508
515
  const cleanupFixed = cleanupResults.filter(r => r.status === 'fixed').length;
509
- console.log(chalk.green(`✅ Cleaned duplicate roles in ${cleanupFixed} files`));
516
+ console.log(chalk.green(`✅ Đã dọn dẹp role trùng lặp trong ${cleanupFixed} file`));
510
517
 
511
- showCompletionMessage(options, 'Heading structure fixes + cleanup');
518
+ showCompletionMessage(options, 'Sửa cấu trúc heading + dọn dẹp');
512
519
  return;
513
520
 
514
521
  } else if (options.dlOnly) {
515
522
  // Fix description lists + cleanup
516
- console.log(chalk.blue('📋 Running description list fixes + cleanup...'));
523
+ console.log(chalk.blue('📋 Đang sửa danh sách mô tả + dọn dẹp...'));
517
524
  const dlResults = await fixer.fixDescriptionLists(options.directory);
518
525
  const dlFixed = dlResults.filter(r => r.status === 'fixed').length;
519
526
  const totalDlIssues = dlResults.reduce((sum, r) => sum + (r.issues || 0), 0);
520
527
 
521
- console.log(chalk.green(`\n✅ Fixed description lists in ${dlFixed} files (${totalDlIssues} issues)`));
528
+ console.log(chalk.green(`\n✅ Đã sửa danh sách mô tả trong ${dlFixed} file (${totalDlIssues} vấn đề)`));
522
529
 
523
530
  // Run cleanup
524
- console.log(chalk.blue('\n🧹 Running cleanup for duplicate role attributes...'));
531
+ console.log(chalk.blue('\n🧹 Đang dọn dẹp các thuộc tính role trùng lặp...'));
525
532
  const cleanupResults = await fixer.cleanupDuplicateRoles(options.directory);
526
533
  const cleanupFixed = cleanupResults.filter(r => r.status === 'fixed').length;
527
- console.log(chalk.green(`✅ Cleaned duplicate roles in ${cleanupFixed} files`));
534
+ console.log(chalk.green(`✅ Đã dọn dẹp role trùng lặp trong ${cleanupFixed} file`));
528
535
 
529
- showCompletionMessage(options, 'Description list fixes + cleanup');
536
+ showCompletionMessage(options, 'Sửa danh sách mô tả + dọn dẹp');
530
537
  return;
531
538
 
532
539
  } else if (options.linksCheckOnly) {
533
540
  // Check broken links and 404 resources (backward compatibility)
534
- console.log(chalk.blue('🔗 Running comprehensive links and resources check...'));
541
+ console.log(chalk.blue('🔗 Đang kiểm tra link tài nguyên toàn diện...'));
535
542
  const linkResults = await fixer.checkBrokenLinks(options.directory);
536
543
  const resourceResults = await fixer.check404Resources(options.directory);
537
544
  const totalLinkIssues = linkResults.reduce((sum, r) => sum + (r.issues || 0), 0);
538
545
  const totalResourceIssues = resourceResults.reduce((sum, r) => sum + (r.issues || 0), 0);
539
546
 
540
- console.log(chalk.green(`\n✅ Checked links in ${linkResults.length} files (${totalLinkIssues} link issues found)`));
541
- console.log(chalk.green(`✅ Checked resources in ${resourceResults.length} files (${totalResourceIssues} resource issues found)`));
542
- console.log(chalk.gray('💡 Link and resource issues require manual review and cannot be auto-fixed'));
547
+ console.log(chalk.green(`\n✅ Đã kiểm tra link trong ${linkResults.length} file (${totalLinkIssues} vấn đề link)`));
548
+ console.log(chalk.green(`✅ Đã kiểm tra tài nguyên trong ${resourceResults.length} file (${totalResourceIssues} vấn đề tài nguyên)`));
549
+ console.log(chalk.gray('💡 Vấn đề về link tài nguyên cần xem xét thủ công và không thể tự động sửa'));
543
550
 
544
- showCompletionMessage(options, 'Links and resources check');
551
+ showCompletionMessage(options, 'Kiểm tra link và tài nguyên');
545
552
  return;
546
553
 
547
554
  } else if (options.brokenLinksOnly) {
548
555
  // Check broken external links only
549
- console.log(chalk.blue('🔗 Running broken external links check only...'));
556
+ console.log(chalk.blue('🔗 Đang kiểm tra link bên ngoài bị lỗi...'));
550
557
  const linkResults = await fixer.checkBrokenLinks(options.directory);
551
558
  const totalBrokenLinks = linkResults.reduce((sum, r) => sum + (r.issues || 0), 0);
552
559
 
553
- console.log(chalk.green(`\n✅ Checked external links in ${linkResults.length} files (${totalBrokenLinks} issues found)`));
554
- console.log(chalk.gray('💡 Broken link issues require manual review and cannot be auto-fixed'));
560
+ console.log(chalk.green(`\n✅ Đã kiểm tra link bên ngoài trong ${linkResults.length} file (${totalBrokenLinks} vấn đề)`));
561
+ console.log(chalk.gray('💡 Vấn đề link bị lỗi cần xem xét thủ công và không thể tự động sửa'));
555
562
 
556
- showCompletionMessage(options, 'Broken external links check');
563
+ showCompletionMessage(options, 'Kiểm tra link bị lỗi');
557
564
  return;
558
565
 
559
566
  } else if (options.missingResourcesOnly) {
560
567
  // Check 404 resources only (missing local files)
561
- console.log(chalk.blue('📁 Running missing resources check only...'));
568
+ console.log(chalk.blue('📁 Đang kiểm tra tài nguyên thiếu...'));
562
569
  const resourceResults = await fixer.check404Resources(options.directory);
563
570
  const totalMissingResources = resourceResults.reduce((sum, r) => sum + (r.issues || 0), 0);
564
571
 
565
- console.log(chalk.green(`\n✅ Checked local resources in ${resourceResults.length} files (${totalMissingResources} issues found)`));
566
- console.log(chalk.gray('💡 Missing resource issues require manual review and cannot be auto-fixed'));
572
+ console.log(chalk.green(`\n✅ Đã kiểm tra tài nguyên cục bộ trong ${resourceResults.length} file (${totalMissingResources} vấn đề)`));
573
+ console.log(chalk.gray('💡 Vấn đề tài nguyên thiếu cần xem xét thủ công và không thể tự động sửa'));
574
+
575
+ showCompletionMessage(options, 'Kiểm tra tài nguyên thiếu');
576
+ return;
577
+
578
+ } else if (options.gtmCheckOnly) {
579
+ // Check Google Tag Manager installation only (no fixes)
580
+ console.log(chalk.blue('🏷️ Đang kiểm tra Google Tag Manager...'));
581
+ const gtmResults = await fixer.checkGoogleTagManager(options.directory);
582
+ const filesWithGTM = gtmResults.filter(r => r.gtmAnalysis?.hasGTM).length;
583
+ const filesWithIssues = gtmResults.filter(r => r.gtmAnalysis?.issues?.length > 0).length;
584
+
585
+ console.log(chalk.green(`\n✅ Phân tích hoàn tất: Tìm thấy ${filesWithGTM} file có GTM`));
586
+ if (filesWithIssues > 0) {
587
+ console.log(chalk.yellow(`⚠️ ${filesWithIssues} file có vấn đề về cài đặt GTM`));
588
+ }
589
+ console.log(chalk.gray('💡 GTM cần có cả <script> trong <head> và <noscript> sau <body>'));
567
590
 
568
- showCompletionMessage(options, 'Missing resources check');
591
+ showCompletionMessage(options, 'Kiểm tra GTM');
569
592
  return;
570
593
 
571
594
  } else if (options.unusedFilesOnly) {
572
595
  // Check unused files only (no fixes, no cleanup)
573
- console.log(chalk.blue('🗂️ Running unused files check only...'));
596
+ console.log(chalk.blue('🗂️ Đang kiểm tra file không sử dụng...'));
574
597
  const unusedResults = await fixer.checkUnusedFiles(options.directory);
575
598
  const totalUnusedFiles = unusedResults.unusedCount;
576
599
 
577
600
  if (totalUnusedFiles === 0) {
578
- console.log(chalk.green(`\n✅ No unused files found! All ${unusedResults.totalFiles} files are properly referenced.`));
601
+ console.log(chalk.green(`\n✅ Không tìm thấy file không sử dụng! Tất cả ${unusedResults.totalFiles} file đều được tham chiếu đúng cách.`));
579
602
  } else {
580
- console.log(chalk.green(`\n✅ Analysis complete: Found ${totalUnusedFiles} unused files out of ${unusedResults.totalFiles} total files`));
581
- console.log(chalk.gray(`📊 ${unusedResults.referencedFiles} files are referenced, ${totalUnusedFiles} potentially unused`));
603
+ console.log(chalk.green(`\n✅ Phân tích hoàn tất: Tìm thấy ${totalUnusedFiles} file không sử dụng trong tổng số ${unusedResults.totalFiles} file`));
604
+ console.log(chalk.gray(`📊 ${unusedResults.referencedFiles} file được tham chiếu, ${totalUnusedFiles} file có thể không sử dụng`));
582
605
  }
583
- console.log(chalk.gray('💡 Unused file detection is heuristic - manual review recommended'));
606
+ console.log(chalk.gray('💡 Phát hiện file không sử dụng dựa trên heuristic - khuyến nghị xem xét thủ công'));
584
607
 
585
- showCompletionMessage(options, 'Unused files check');
608
+ showCompletionMessage(options, 'Kiểm tra file không sử dụng');
586
609
  return;
587
610
 
588
611
  } else if (options.deadCodeOnly) {
589
612
  // Check dead code only (no fixes, no cleanup)
590
- console.log(chalk.blue('☠️ Running dead code check only...'));
613
+ console.log(chalk.blue('☠️ Đang kiểm tra không sử dụng...'));
591
614
  const deadCodeResults = await fixer.checkDeadCode(options.directory);
592
615
  const totalDeadCode = deadCodeResults.length;
593
616
 
594
- console.log(chalk.green(`\n✅ Checked for dead code (${totalDeadCode} potential issues found)`));
595
- console.log(chalk.gray('💡 Dead code analysis is heuristic - manual review recommended'));
617
+ console.log(chalk.green(`\n✅ Đã kiểm tra không sử dụng (${totalDeadCode} vấn đề tiềm ẩn)`));
618
+ console.log(chalk.gray('💡 Phân tích không sử dụng dựa trên heuristic - khuyến nghị xem xét thủ công'));
596
619
 
597
- showCompletionMessage(options, 'Dead code check');
620
+ showCompletionMessage(options, 'Kiểm tra mã không sử dụng');
598
621
  return;
599
622
 
600
623
  } else if (options.fileSizeOnly) {
601
624
  // Check file sizes only (no fixes, no cleanup)
602
- console.log(chalk.blue('📏 Running file size analysis only...'));
625
+ console.log(chalk.blue('📏 Đang phân tích kích thước file...'));
603
626
  const sizeResults = await fixer.checkFileSizes(options.directory);
604
627
  const totalLargeFiles = sizeResults.largeFiles.length;
605
628
 
606
- console.log(chalk.green(`\n✅ Analyzed ${sizeResults.totalFiles} files (${totalLargeFiles} large files found)`));
607
- console.log(chalk.gray('💡 File size analysis is based on common best practices'));
629
+ console.log(chalk.green(`\n✅ Đã phân tích ${sizeResults.totalFiles} file (${totalLargeFiles} file kích thước lớn)`));
630
+ console.log(chalk.gray('💡 Phân tích kích thước file dựa trên best practices phổ biến'));
608
631
 
609
- showCompletionMessage(options, 'File size analysis');
632
+ showCompletionMessage(options, 'Phân tích kích thước file');
610
633
  return;
611
634
  }
612
635
 
613
636
  } catch (error) {
614
- console.error(chalk.red('❌ Error occurred:'), error.message);
637
+ console.error(chalk.red('❌ Đã xảy ra lỗi:'), error.message);
615
638
  process.exit(1);
616
639
  }
617
640
  }