mirror of
https://github.com/kamranahmedse/developer-roadmap.git
synced 2025-08-21 16:41:24 +02:00
156 lines
4.7 KiB
Plaintext
156 lines
4.7 KiB
Plaintext
---
|
|
description: When user requests migrating old roadmap content to new folder from content-old to content folder
|
|
globs:
|
|
alwaysApply: false
|
|
---
|
|
# Content Migration Rule
|
|
|
|
## Rule Name: content-migration
|
|
|
|
## Description
|
|
This rule provides a complete process for migrating roadmap content from old structure to new structure using migration mapping files.
|
|
|
|
## When to Use
|
|
Use this rule when you need to:
|
|
- Migrate content from content-old directories to content directories
|
|
- Use a migration-mapping.json file to map topic paths to content IDs
|
|
- Populate empty content files with existing content from legacy structure
|
|
|
|
## Process
|
|
|
|
### 1. Prerequisites Check
|
|
- Verify the roadmap directory has a `migration-mapping.json` file
|
|
- Confirm `content-old/` directory exists with source content
|
|
- Confirm `content/` directory exists with target files
|
|
|
|
### 2. Migration Script Creation
|
|
Create a Node.js script with the following functionality:
|
|
|
|
```javascript
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
// Load the migration mapping
|
|
const migrationMapping = JSON.parse(fs.readFileSync('migration-mapping.json', 'utf8'));
|
|
|
|
// Function to find old content file based on topic path
|
|
function findOldContentFile(topicPath) {
|
|
const parts = topicPath.split(':');
|
|
|
|
if (parts.length === 1) {
|
|
// Top level file like "introduction"
|
|
return path.join('content-old', parts[0], 'index.md');
|
|
} else if (parts.length === 2) {
|
|
// Like "introduction:what-is-rust"
|
|
const [folder, filename] = parts;
|
|
return path.join('content-old', folder, `${filename}.md`);
|
|
} else if (parts.length === 3) {
|
|
// Like "language-basics:syntax:variables"
|
|
const [folder, subfolder, filename] = parts;
|
|
return path.join('content-old', folder, subfolder, `${filename}.md`);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
// Function to find new content file based on content ID
|
|
function findNewContentFile(contentId) {
|
|
const contentDir = 'content';
|
|
const files = fs.readdirSync(contentDir);
|
|
|
|
// Find file that ends with the content ID
|
|
const matchingFile = files.find(file => file.includes(`@${contentId}.md`));
|
|
|
|
if (matchingFile) {
|
|
return path.join(contentDir, matchingFile);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
// Process each mapping
|
|
console.log('Starting content migration...\n');
|
|
|
|
let migratedCount = 0;
|
|
let skippedCount = 0;
|
|
|
|
for (const [topicPath, contentId] of Object.entries(migrationMapping)) {
|
|
const oldFilePath = findOldContentFile(topicPath);
|
|
const newFilePath = findNewContentFile(contentId);
|
|
|
|
if (!oldFilePath) {
|
|
console.log(`❌ Could not determine old file path for: ${topicPath}`);
|
|
skippedCount++;
|
|
continue;
|
|
}
|
|
|
|
if (!newFilePath) {
|
|
console.log(`❌ Could not find new file for content ID: ${contentId} (topic: ${topicPath})`);
|
|
skippedCount++;
|
|
continue;
|
|
}
|
|
|
|
if (!fs.existsSync(oldFilePath)) {
|
|
console.log(`❌ Old file does not exist: ${oldFilePath} (topic: ${topicPath})`);
|
|
skippedCount++;
|
|
continue;
|
|
}
|
|
|
|
try {
|
|
// Read old content
|
|
const oldContent = fs.readFileSync(oldFilePath, 'utf8');
|
|
|
|
// Write to new file
|
|
fs.writeFileSync(newFilePath, oldContent);
|
|
|
|
console.log(`✅ Migrated: ${topicPath} -> ${path.basename(newFilePath)}`);
|
|
migratedCount++;
|
|
} catch (error) {
|
|
console.log(`❌ Error migrating ${topicPath}: ${error.message}`);
|
|
skippedCount++;
|
|
}
|
|
}
|
|
|
|
console.log(`\n📊 Migration complete:`);
|
|
console.log(` Migrated: ${migratedCount} files`);
|
|
console.log(` Skipped: ${skippedCount} files`);
|
|
console.log(` Total: ${Object.keys(migrationMapping).length} mappings`);
|
|
```
|
|
|
|
### 3. Execution Steps
|
|
1. Navigate to the roadmap directory (e.g., `src/data/roadmaps/[roadmap-name]`)
|
|
2. Create the migration script as `migrate_content.cjs`
|
|
3. Run: `node migrate_content.cjs`
|
|
4. Review the migration results
|
|
5. Clean up the temporary script file
|
|
|
|
### 4. Validation
|
|
After migration:
|
|
- Verify a few migrated files have proper content (not just titles)
|
|
- Check that the content structure matches the old content
|
|
- Ensure proper markdown formatting is preserved
|
|
|
|
## File Structure Expected
|
|
```
|
|
roadmap-directory/
|
|
├── migration-mapping.json
|
|
├── content/
|
|
│ ├── file1@contentId1.md
|
|
│ ├── file2@contentId2.md
|
|
│ └── ...
|
|
└── content-old/
|
|
├── section1/
|
|
│ ├── index.md
|
|
│ ├── topic1.md
|
|
│ └── subsection1/
|
|
│ └── subtopic1.md
|
|
└── section2/
|
|
└── ...
|
|
```
|
|
|
|
## Notes
|
|
- The migration mapping uses colons (`:`) to separate nested paths
|
|
- Content files in the new structure use the pattern `filename@contentId.md`
|
|
- The script handles 1-3 levels of nesting in the old structure
|
|
- Always create the script with `.cjs` extension to avoid ES module issues
|