extract into brand profile
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* Rule Transformer Module
|
* Rule Transformer Module
|
||||||
* Handles conversion of Cursor rules to Roo rules
|
* Handles conversion of Cursor rules to brand rules
|
||||||
*
|
*
|
||||||
* This module procedurally generates .roo/rules files from .cursor/rules files,
|
* This module procedurally generates .{brand}/rules files from .cursor/rules files,
|
||||||
* eliminating the need to maintain both sets of files manually.
|
* eliminating the need to maintain both sets of files manually.
|
||||||
*/
|
*/
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
@@ -95,64 +95,45 @@ function updateFileReferences(content) {
|
|||||||
/**
|
/**
|
||||||
* Main transformation function that applies all conversions
|
* Main transformation function that applies all conversions
|
||||||
*/
|
*/
|
||||||
function transformCursorToRooRules(content) {
|
// Main transformation function that applies all conversions, now brand-generic
|
||||||
|
function transformCursorToBrandRules(content, conversionConfig, globalReplacements = []) {
|
||||||
// Apply all transformations in appropriate order
|
// Apply all transformations in appropriate order
|
||||||
let result = content;
|
let result = content;
|
||||||
result = replaceBasicTerms(result);
|
result = replaceBasicTerms(result, conversionConfig);
|
||||||
result = replaceToolReferences(result);
|
result = replaceToolReferences(result, conversionConfig);
|
||||||
result = updateDocReferences(result);
|
result = updateDocReferences(result, conversionConfig);
|
||||||
result = updateFileReferences(result);
|
result = updateFileReferences(result, conversionConfig);
|
||||||
|
|
||||||
|
// Apply any global/catch-all replacements from the brand profile
|
||||||
// Super aggressive failsafe pass to catch any variations we might have missed
|
// Super aggressive failsafe pass to catch any variations we might have missed
|
||||||
// This ensures critical transformations are applied even in contexts we didn't anticipate
|
// This ensures critical transformations are applied even in contexts we didn't anticipate
|
||||||
|
globalReplacements.forEach((pattern) => {
|
||||||
// 1. Handle cursor.so in any possible context
|
if (typeof pattern.to === 'function') {
|
||||||
result = result.replace(/cursor\.so/gi, 'roocode.com');
|
result = result.replace(pattern.from, pattern.to);
|
||||||
// Edge case: URL with different formatting
|
} else {
|
||||||
result = result.replace(/cursor\s*\.\s*so/gi, 'roocode.com');
|
result = result.replace(pattern.from, pattern.to);
|
||||||
result = result.replace(/https?:\/\/cursor\.so/gi, 'https://roocode.com');
|
}
|
||||||
result = result.replace(
|
});
|
||||||
/https?:\/\/www\.cursor\.so/gi,
|
|
||||||
'https://www.roocode.com'
|
|
||||||
);
|
|
||||||
|
|
||||||
// 2. Handle tool references - even partial ones
|
|
||||||
result = result.replace(/\bedit_file\b/gi, 'apply_diff');
|
|
||||||
result = result.replace(/\bsearch tool\b/gi, 'search_files tool');
|
|
||||||
result = result.replace(/\bSearch Tool\b/g, 'Search_Files Tool');
|
|
||||||
|
|
||||||
// 3. Handle basic terms (with case handling)
|
|
||||||
result = result.replace(/\bcursor\b/gi, (match) =>
|
|
||||||
match.charAt(0) === 'C' ? 'Roo Code' : 'roo'
|
|
||||||
);
|
|
||||||
result = result.replace(/Cursor/g, 'Roo Code');
|
|
||||||
result = result.replace(/CURSOR/g, 'ROO CODE');
|
|
||||||
|
|
||||||
// 4. Handle file extensions
|
|
||||||
result = result.replace(/\.mdc\b/g, '.md');
|
|
||||||
|
|
||||||
// 5. Handle any missed URL patterns
|
|
||||||
result = result.replace(/docs\.cursor\.com/gi, 'docs.roocode.com');
|
|
||||||
result = result.replace(/docs\.roo\.com/gi, 'docs.roocode.com');
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a single Cursor rule file to Roo rule format
|
* Convert a single Cursor rule file to brand rule format
|
||||||
*/
|
*/
|
||||||
function convertCursorRuleToRooRule(sourcePath, targetPath) {
|
function convertCursorRuleToBrandRule(sourcePath, targetPath, profile) {
|
||||||
|
const { conversionConfig, brandName, globalReplacements } = profile;
|
||||||
try {
|
try {
|
||||||
log(
|
log(
|
||||||
'info',
|
'info',
|
||||||
`Converting Cursor rule ${path.basename(sourcePath)} to Roo rule ${path.basename(targetPath)}`
|
`Converting Cursor rule ${path.basename(sourcePath)} to ${brandName} rule ${path.basename(targetPath)}`
|
||||||
);
|
);
|
||||||
|
|
||||||
// Read source content
|
// Read source content
|
||||||
const content = fs.readFileSync(sourcePath, 'utf8');
|
const content = fs.readFileSync(sourcePath, 'utf8');
|
||||||
|
|
||||||
// Transform content
|
// Transform content
|
||||||
const transformedContent = transformCursorToRooRules(content);
|
const transformedContent = transformCursorToBrandRules(content, conversionConfig, globalReplacements);
|
||||||
|
|
||||||
// Ensure target directory exists
|
// Ensure target directory exists
|
||||||
const targetDir = path.dirname(targetPath);
|
const targetDir = path.dirname(targetPath);
|
||||||
@@ -178,21 +159,22 @@ function convertCursorRuleToRooRule(sourcePath, targetPath) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process all Cursor rules and convert to Roo rules
|
* Process all Cursor rules and convert to brand rules
|
||||||
*/
|
*/
|
||||||
function convertAllCursorRulesToRooRules(projectDir) {
|
function convertAllCursorRulesToBrandRules(projectDir, profile) {
|
||||||
|
const { fileMap, brandName, rulesDir } = profile;
|
||||||
const cursorRulesDir = path.join(projectDir, '.cursor', 'rules');
|
const cursorRulesDir = path.join(projectDir, '.cursor', 'rules');
|
||||||
const rooRulesDir = path.join(projectDir, '.roo', 'rules');
|
const brandRulesDir = path.join(projectDir, rulesDir);
|
||||||
|
|
||||||
if (!fs.existsSync(cursorRulesDir)) {
|
if (!fs.existsSync(cursorRulesDir)) {
|
||||||
log('warn', `Cursor rules directory not found: ${cursorRulesDir}`);
|
log('warn', `Cursor rules directory not found: ${cursorRulesDir}`);
|
||||||
return { success: 0, failed: 0 };
|
return { success: 0, failed: 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure Roo rules directory exists
|
// Ensure brand rules directory exists
|
||||||
if (!fs.existsSync(rooRulesDir)) {
|
if (!fs.existsSync(brandRulesDir)) {
|
||||||
fs.mkdirSync(rooRulesDir, { recursive: true });
|
fs.mkdirSync(brandRulesDir, { recursive: true });
|
||||||
log('info', `Created Roo rules directory: ${rooRulesDir}`);
|
log('info', `Created ${brandName} rules directory: ${brandRulesDir}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count successful and failed conversions
|
// Count successful and failed conversions
|
||||||
@@ -206,10 +188,10 @@ function convertAllCursorRulesToRooRules(projectDir) {
|
|||||||
|
|
||||||
// Determine target file name (either from mapping or by replacing extension)
|
// Determine target file name (either from mapping or by replacing extension)
|
||||||
const targetFilename = fileMap[file] || file.replace('.mdc', '.md');
|
const targetFilename = fileMap[file] || file.replace('.mdc', '.md');
|
||||||
const targetPath = path.join(rooRulesDir, targetFilename);
|
const targetPath = path.join(brandRulesDir, targetFilename);
|
||||||
|
|
||||||
// Convert the file
|
// Convert the file
|
||||||
if (convertCursorRuleToRooRule(sourcePath, targetPath)) {
|
if (convertCursorRuleToBrandRule(sourcePath, targetPath, profile)) {
|
||||||
success++;
|
success++;
|
||||||
} else {
|
} else {
|
||||||
failed++;
|
failed++;
|
||||||
@@ -224,4 +206,4 @@ function convertAllCursorRulesToRooRules(projectDir) {
|
|||||||
return { success, failed };
|
return { success, failed };
|
||||||
}
|
}
|
||||||
|
|
||||||
export { convertAllCursorRulesToRooRules, convertCursorRuleToRooRule };
|
export { convertAllCursorRulesToBrandRules, convertCursorRuleToBrandRule };
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
// Roo Code conversion profile for rule-transformer
|
// Roo Code conversion profile for rule-transformer
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
|
||||||
|
const brandName = 'Roo';
|
||||||
|
const rulesDir = '.roo/rules';
|
||||||
|
|
||||||
// File name mapping (specific files with naming changes)
|
// File name mapping (specific files with naming changes)
|
||||||
const fileMap = {
|
const fileMap = {
|
||||||
'cursor_rules.mdc': 'roo_rules.md',
|
'cursor_rules.mdc': 'roo_rules.md',
|
||||||
@@ -10,6 +13,28 @@ const fileMap = {
|
|||||||
// Add other mappings as needed
|
// Add other mappings as needed
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const globalReplacements = [
|
||||||
|
// 1. Handle cursor.so in any possible context
|
||||||
|
{ from: /cursor\.so/gi, to: 'roocode.com' },
|
||||||
|
// Edge case: URL with different formatting
|
||||||
|
{ from: /cursor\s*\.\s*so/gi, to: 'roocode.com' },
|
||||||
|
{ from: /https?:\/\/cursor\.so/gi, to: 'https://roocode.com' },
|
||||||
|
{ from: /https?:\/\/www\.cursor\.so/gi, to: 'https://www.roocode.com' },
|
||||||
|
// 2. Handle tool references - even partial ones
|
||||||
|
{ from: /\bedit_file\b/gi, to: 'apply_diff' },
|
||||||
|
{ from: /\bsearch tool\b/gi, to: 'search_files tool' },
|
||||||
|
{ from: /\bSearch Tool\b/g, to: 'Search_Files Tool' },
|
||||||
|
// 3. Handle basic terms (with case handling)
|
||||||
|
{ from: /\bcursor\b/gi, to: (match) => (match.charAt(0) === 'C' ? 'Roo Code' : 'roo') },
|
||||||
|
{ from: /Cursor/g, to: 'Roo Code' },
|
||||||
|
{ from: /CURSOR/g, to: 'ROO CODE' },
|
||||||
|
// 4. Handle file extensions
|
||||||
|
{ from: /\.mdc\b/g, to: '.md' },
|
||||||
|
// 5. Handle any missed URL patterns
|
||||||
|
{ from: /docs\.cursor\.com/gi, to: 'docs.roocode.com' },
|
||||||
|
{ from: /docs\.roo\.com/gi, to: 'docs.roocode.com' }
|
||||||
|
];
|
||||||
|
|
||||||
const conversionConfig = {
|
const conversionConfig = {
|
||||||
// Product and brand name replacements
|
// Product and brand name replacements
|
||||||
brandTerms: [
|
brandTerms: [
|
||||||
@@ -87,4 +112,4 @@ const conversionConfig = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export { conversionConfig, fileMap };
|
export { conversionConfig, fileMap, globalReplacements, brandName, rulesDir };
|
||||||
|
|||||||
Reference in New Issue
Block a user