ultimate-jekyll-manager 0.0.136 → 0.0.137
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/dist/commands/setup.js +121 -1
- package/package.json +1 -1
package/dist/commands/setup.js
CHANGED
|
@@ -42,6 +42,7 @@ module.exports = async function (options) {
|
|
|
42
42
|
options.updateBundle = options.updateBundle !== 'false';
|
|
43
43
|
options.publishGitHubToken = options.publishGitHubToken !== 'false';
|
|
44
44
|
options.updateGitHubPages = options.updateGitHubPages !== 'false';
|
|
45
|
+
options.deduplicatePosts = options.deduplicatePosts !== 'false';
|
|
45
46
|
|
|
46
47
|
// Log
|
|
47
48
|
logger.log(`Welcome to ${package.name} v${package.version}!`);
|
|
@@ -125,6 +126,11 @@ module.exports = async function (options) {
|
|
|
125
126
|
if (options.updateBundle && !Manager.isServer()) {
|
|
126
127
|
await updateBundle();
|
|
127
128
|
}
|
|
129
|
+
|
|
130
|
+
// Deduplicate posts (remove duplicate posts with same slug but different dates)
|
|
131
|
+
if (options.deduplicatePosts) {
|
|
132
|
+
await deduplicatePosts();
|
|
133
|
+
}
|
|
128
134
|
} catch (e) {
|
|
129
135
|
// Throw error
|
|
130
136
|
throw e;
|
|
@@ -599,7 +605,7 @@ async function updateGitHubPages(options) {
|
|
|
599
605
|
owner,
|
|
600
606
|
repo,
|
|
601
607
|
source: sourceConfig,
|
|
602
|
-
|
|
608
|
+
};
|
|
603
609
|
|
|
604
610
|
// Add custom domain if available and not github.io domain
|
|
605
611
|
if (customDomain && !customDomain.includes('github.io')) {
|
|
@@ -654,3 +660,117 @@ async function updateGitHubPages(options) {
|
|
|
654
660
|
// Don't throw - this is not critical for setup to continue
|
|
655
661
|
}
|
|
656
662
|
}
|
|
663
|
+
|
|
664
|
+
// Deduplicate posts - removes duplicate posts with same slug but different dates
|
|
665
|
+
// Keeps the ORIGINAL (oldest) post and removes newer duplicates
|
|
666
|
+
async function deduplicatePosts() {
|
|
667
|
+
logger.log('🔍 Checking for duplicate posts...');
|
|
668
|
+
|
|
669
|
+
// Find all post files in src/_posts
|
|
670
|
+
const postsGlob = 'src/_posts/**/*.{md,markdown,html}';
|
|
671
|
+
const postFiles = glob(postsGlob, { nodir: true });
|
|
672
|
+
|
|
673
|
+
if (postFiles.length === 0) {
|
|
674
|
+
logger.log('No posts found');
|
|
675
|
+
return;
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
logger.log(`Found ${postFiles.length} post files`);
|
|
679
|
+
|
|
680
|
+
// Group posts by slug (filename without date prefix)
|
|
681
|
+
const postsBySlug = {};
|
|
682
|
+
|
|
683
|
+
for (const filePath of postFiles) {
|
|
684
|
+
const filename = path.basename(filePath);
|
|
685
|
+
|
|
686
|
+
// Jekyll post format: YYYY-MM-DD-slug.ext
|
|
687
|
+
const match = filename.match(/^(\d{4}-\d{2}-\d{2})-(.+)\.(md|markdown|html)$/);
|
|
688
|
+
|
|
689
|
+
if (!match) {
|
|
690
|
+
continue;
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
const [, dateStr, slug, ext] = match;
|
|
694
|
+
const date = new Date(dateStr);
|
|
695
|
+
|
|
696
|
+
if (!postsBySlug[slug]) {
|
|
697
|
+
postsBySlug[slug] = [];
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
postsBySlug[slug].push({
|
|
701
|
+
filePath,
|
|
702
|
+
filename,
|
|
703
|
+
date,
|
|
704
|
+
dateStr,
|
|
705
|
+
slug,
|
|
706
|
+
ext,
|
|
707
|
+
});
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
// Find duplicates and keep only the ORIGINAL (oldest)
|
|
711
|
+
let removedCount = 0;
|
|
712
|
+
const duplicates = [];
|
|
713
|
+
|
|
714
|
+
for (const [slug, posts] of Object.entries(postsBySlug)) {
|
|
715
|
+
if (posts.length <= 1) {
|
|
716
|
+
continue;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
// Sort by date ascending (oldest first)
|
|
720
|
+
posts.sort((a, b) => a.date - b.date);
|
|
721
|
+
|
|
722
|
+
// Keep the oldest (original), mark the rest for removal
|
|
723
|
+
const [original, ...newer] = posts;
|
|
724
|
+
|
|
725
|
+
logger.log(`Found ${posts.length} posts with slug "${slug}":`);
|
|
726
|
+
logger.log(` ✅ Keeping original: ${original.filename} (${original.dateStr})`);
|
|
727
|
+
|
|
728
|
+
for (const post of newer) {
|
|
729
|
+
logger.log(` ❌ Removing duplicate: ${post.filename} (${post.dateStr})`);
|
|
730
|
+
|
|
731
|
+
// Remove the duplicate post file
|
|
732
|
+
try {
|
|
733
|
+
jetpack.remove(post.filePath);
|
|
734
|
+
removedCount++;
|
|
735
|
+
|
|
736
|
+
// Also remove the associated images folder (src/assets/images/blog/post-SLUG)
|
|
737
|
+
const imageFolder = `src/assets/images/blog/post-${post.slug}`;
|
|
738
|
+
if (jetpack.exists(imageFolder)) {
|
|
739
|
+
jetpack.remove(imageFolder);
|
|
740
|
+
logger.log(` 🗑️ Removed image folder: ${imageFolder}`);
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
duplicates.push({
|
|
744
|
+
kept: original.filename,
|
|
745
|
+
removed: post.filename,
|
|
746
|
+
removedPath: post.filePath,
|
|
747
|
+
slug,
|
|
748
|
+
});
|
|
749
|
+
} catch (error) {
|
|
750
|
+
logger.error(`Failed to remove ${post.filePath}:`, error);
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
// Log summary
|
|
756
|
+
if (removedCount > 0) {
|
|
757
|
+
logger.log(`✅ Removed ${removedCount} duplicate post(s)`);
|
|
758
|
+
|
|
759
|
+
// Save report
|
|
760
|
+
const reportDir = path.join(rootPathProject, '.temp/deduplicate');
|
|
761
|
+
jetpack.dir(reportDir);
|
|
762
|
+
|
|
763
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
764
|
+
const reportPath = path.join(reportDir, `duplicates-${timestamp}.json`);
|
|
765
|
+
|
|
766
|
+
jetpack.write(reportPath, JSON.stringify({
|
|
767
|
+
timestamp: new Date().toISOString(),
|
|
768
|
+
removedCount,
|
|
769
|
+
duplicates,
|
|
770
|
+
}, null, 2));
|
|
771
|
+
|
|
772
|
+
logger.log(`Report saved to: ${reportPath}`);
|
|
773
|
+
} else {
|
|
774
|
+
logger.log('✅ No duplicate posts found');
|
|
775
|
+
}
|
|
776
|
+
}
|