gbu-accessibility-package 3.8.9 → 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/README-vi.md +94 -0
- package/README.md +95 -1
- package/cli.js +128 -105
- package/lib/fixer.js +261 -81
- package/package.json +2 -1
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 = '
|
|
262
|
+
function showCompletionMessage(options, mode = 'sửa lỗi') {
|
|
256
263
|
if (options.dryRun) {
|
|
257
|
-
console.log(chalk.cyan('\n💡
|
|
264
|
+
console.log(chalk.cyan('\n💡 Đây là 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}
|
|
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(' 📁
|
|
262
|
-
console.log(chalk.gray(' 💡
|
|
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(' ⚡
|
|
265
|
-
console.log(chalk.gray(' 💡
|
|
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('🚀
|
|
273
|
-
console.log(chalk.gray(`
|
|
274
|
-
console.log(chalk.gray(`
|
|
275
|
-
console.log(chalk.gray(`Backup: ${options.backupFiles ? '
|
|
276
|
-
console.log(chalk.gray(`
|
|
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 ? 'Có' : '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('🎯
|
|
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('🧹
|
|
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✅
|
|
320
|
+
console.log(chalk.green(`\n✅ Đã dọn dẹp role trùng lặp trong ${cleanupFixed} file`));
|
|
314
321
|
|
|
315
|
-
showCompletionMessage(options, '
|
|
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('🧹
|
|
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✅
|
|
331
|
+
console.log(chalk.green(`\n✅ Đã dọn dẹp role trùng lặp trong ${cleanupFixed} file`));
|
|
325
332
|
|
|
326
|
-
showCompletionMessage(options, '
|
|
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('🖼️
|
|
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✅
|
|
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🧹
|
|
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(`✅
|
|
349
|
+
console.log(chalk.green(`✅ Đã dọn dẹp role trùng lặp trong ${cleanupFixed} file`));
|
|
343
350
|
|
|
344
|
-
showCompletionMessage(options, '
|
|
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('📝
|
|
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✅
|
|
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🧹
|
|
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(`✅
|
|
366
|
+
console.log(chalk.green(`✅ Đã dọn dẹp role trùng lặp trong ${cleanupFixed} file`));
|
|
360
367
|
|
|
361
|
-
showCompletionMessage(options, '
|
|
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('🎭
|
|
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✅
|
|
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🧹
|
|
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(`✅
|
|
384
|
+
console.log(chalk.green(`✅ Đã dọn dẹp role trùng lặp trong ${cleanupFixed} file`));
|
|
378
385
|
|
|
379
|
-
showCompletionMessage(options, '
|
|
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('🏷️
|
|
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✅
|
|
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🧹
|
|
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(`✅
|
|
402
|
+
console.log(chalk.green(`✅ Đã dọn dẹp role trùng lặp trong ${cleanupFixed} file`));
|
|
396
403
|
|
|
397
|
-
showCompletionMessage(options, '
|
|
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('📋
|
|
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✅
|
|
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🧹
|
|
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(`✅
|
|
420
|
+
console.log(chalk.green(`✅ Đã dọn dẹp role trùng lặp trong ${cleanupFixed} file`));
|
|
414
421
|
|
|
415
|
-
showCompletionMessage(options, '
|
|
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('🎯
|
|
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✅
|
|
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🧹
|
|
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(`✅
|
|
438
|
+
console.log(chalk.green(`✅ Đã dọn dẹp role trùng lặp trong ${cleanupFixed} file`));
|
|
432
439
|
|
|
433
|
-
showCompletionMessage(options, '
|
|
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('🔘
|
|
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✅
|
|
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🧹
|
|
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(`✅
|
|
456
|
+
console.log(chalk.green(`✅ Đã dọn dẹp role trùng lặp trong ${cleanupFixed} file`));
|
|
450
457
|
|
|
451
|
-
showCompletionMessage(options, '
|
|
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('🔗
|
|
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✅
|
|
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🧹
|
|
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(`✅
|
|
474
|
+
console.log(chalk.green(`✅ Đã dọn dẹp role trùng lặp trong ${cleanupFixed} file`));
|
|
468
475
|
|
|
469
|
-
showCompletionMessage(options, '
|
|
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('🏛️
|
|
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✅
|
|
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🧹
|
|
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(`✅
|
|
492
|
+
console.log(chalk.green(`✅ Đã dọn dẹp role trùng lặp trong ${cleanupFixed} file`));
|
|
486
493
|
|
|
487
|
-
showCompletionMessage(options, '
|
|
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('📑
|
|
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✅
|
|
505
|
+
console.log(chalk.green(`\n✅ Đã xử lý heading trong ${headingResults.length} file (${totalHeadingIssues} vấn đề tìm thấy)`));
|
|
499
506
|
if (options.autoFixHeadings) {
|
|
500
|
-
console.log(chalk.green(`✅
|
|
507
|
+
console.log(chalk.green(`✅ Đã sửa ${totalHeadingFixes} vấn đề heading tự động`));
|
|
501
508
|
} else {
|
|
502
|
-
console.log(chalk.gray('💡
|
|
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🧹
|
|
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(`✅
|
|
516
|
+
console.log(chalk.green(`✅ Đã dọn dẹp role trùng lặp trong ${cleanupFixed} file`));
|
|
510
517
|
|
|
511
|
-
showCompletionMessage(options, '
|
|
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('📋
|
|
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✅
|
|
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🧹
|
|
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(`✅
|
|
534
|
+
console.log(chalk.green(`✅ Đã dọn dẹp role trùng lặp trong ${cleanupFixed} file`));
|
|
528
535
|
|
|
529
|
-
showCompletionMessage(options, '
|
|
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('🔗
|
|
541
|
+
console.log(chalk.blue('🔗 Đang kiểm tra link và 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✅
|
|
541
|
-
console.log(chalk.green(`✅
|
|
542
|
-
console.log(chalk.gray('💡
|
|
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 và 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, '
|
|
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('🔗
|
|
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✅
|
|
554
|
-
console.log(chalk.gray('💡
|
|
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, '
|
|
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('📁
|
|
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✅
|
|
566
|
-
console.log(chalk.gray('💡
|
|
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, '
|
|
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('🗂️
|
|
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✅
|
|
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✅
|
|
581
|
-
console.log(chalk.gray(`📊 ${unusedResults.referencedFiles}
|
|
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('💡
|
|
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, '
|
|
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('☠️
|
|
613
|
+
console.log(chalk.blue('☠️ Đang kiểm tra mã 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✅
|
|
595
|
-
console.log(chalk.gray('💡
|
|
617
|
+
console.log(chalk.green(`\n✅ Đã kiểm tra mã không sử dụng (${totalDeadCode} vấn đề tiềm ẩn)`));
|
|
618
|
+
console.log(chalk.gray('💡 Phân tích mã không sử dụng dựa trên heuristic - khuyến nghị xem xét thủ công'));
|
|
596
619
|
|
|
597
|
-
showCompletionMessage(options, '
|
|
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('📏
|
|
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✅
|
|
607
|
-
console.log(chalk.gray('💡
|
|
629
|
+
console.log(chalk.green(`\n✅ Đã phân tích ${sizeResults.totalFiles} file (${totalLargeFiles} file có 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, '
|
|
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('❌
|
|
637
|
+
console.error(chalk.red('❌ Đã xảy ra lỗi:'), error.message);
|
|
615
638
|
process.exit(1);
|
|
616
639
|
}
|
|
617
640
|
}
|