mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-04-14 05:43:29 +08:00
Merge pull request #1393 from affaan-m/fix/cursor-rule-mdc-install
fix: install Cursor rules as .mdc files
This commit is contained in:
@@ -1,11 +1,23 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const {
|
||||
createFlatRuleOperations,
|
||||
createInstallTargetAdapter,
|
||||
createManagedOperation,
|
||||
isForeignPlatformPath,
|
||||
} = require('./helpers');
|
||||
|
||||
function toCursorRuleFileName(fileName, sourceRelativeFile) {
|
||||
if (path.basename(sourceRelativeFile).toLowerCase() === 'readme.md') {
|
||||
return null;
|
||||
}
|
||||
|
||||
return fileName.endsWith('.md')
|
||||
? `${fileName.slice(0, -3)}.mdc`
|
||||
: fileName;
|
||||
}
|
||||
|
||||
module.exports = createInstallTargetAdapter({
|
||||
id: 'cursor-project',
|
||||
target: 'cursor',
|
||||
@@ -17,6 +29,7 @@ module.exports = createInstallTargetAdapter({
|
||||
const modules = Array.isArray(input.modules)
|
||||
? input.modules
|
||||
: (input.module ? [input.module] : []);
|
||||
const seenDestinationPaths = new Set();
|
||||
const {
|
||||
repoRoot,
|
||||
projectRoot,
|
||||
@@ -28,23 +41,98 @@ module.exports = createInstallTargetAdapter({
|
||||
homeDir,
|
||||
};
|
||||
const targetRoot = adapter.resolveRoot(planningInput);
|
||||
|
||||
return modules.flatMap(module => {
|
||||
const entries = modules.flatMap((module, moduleIndex) => {
|
||||
const paths = Array.isArray(module.paths) ? module.paths : [];
|
||||
return paths
|
||||
.filter(p => !isForeignPlatformPath(p, adapter.target))
|
||||
.flatMap(sourceRelativePath => {
|
||||
if (sourceRelativePath === 'rules') {
|
||||
return createFlatRuleOperations({
|
||||
moduleId: module.id,
|
||||
repoRoot,
|
||||
sourceRelativePath,
|
||||
destinationDir: path.join(targetRoot, 'rules'),
|
||||
});
|
||||
}
|
||||
.map((sourceRelativePath, pathIndex) => ({
|
||||
module,
|
||||
sourceRelativePath,
|
||||
moduleIndex,
|
||||
pathIndex,
|
||||
}));
|
||||
}).sort((left, right) => {
|
||||
const getPriority = value => {
|
||||
if (value === 'rules') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return [adapter.createScaffoldOperation(module.id, sourceRelativePath, planningInput)];
|
||||
if (value === '.cursor') {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 2;
|
||||
};
|
||||
|
||||
const leftPriority = getPriority(left.sourceRelativePath);
|
||||
const rightPriority = getPriority(right.sourceRelativePath);
|
||||
if (leftPriority !== rightPriority) {
|
||||
return leftPriority - rightPriority;
|
||||
}
|
||||
|
||||
if (left.moduleIndex !== right.moduleIndex) {
|
||||
return left.moduleIndex - right.moduleIndex;
|
||||
}
|
||||
|
||||
return left.pathIndex - right.pathIndex;
|
||||
});
|
||||
|
||||
function takeUniqueOperations(operations) {
|
||||
return operations.filter(operation => {
|
||||
if (!operation || !operation.destinationPath) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (seenDestinationPaths.has(operation.destinationPath)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
seenDestinationPaths.add(operation.destinationPath);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
return entries.flatMap(({ module, sourceRelativePath }) => {
|
||||
if (sourceRelativePath === 'rules') {
|
||||
return takeUniqueOperations(createFlatRuleOperations({
|
||||
moduleId: module.id,
|
||||
repoRoot,
|
||||
sourceRelativePath,
|
||||
destinationDir: path.join(targetRoot, 'rules'),
|
||||
destinationNameTransform: toCursorRuleFileName,
|
||||
}));
|
||||
}
|
||||
|
||||
if (sourceRelativePath === '.cursor') {
|
||||
const cursorRoot = path.join(repoRoot, '.cursor');
|
||||
if (!fs.existsSync(cursorRoot) || !fs.statSync(cursorRoot).isDirectory()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const childOperations = fs.readdirSync(cursorRoot, { withFileTypes: true })
|
||||
.sort((left, right) => left.name.localeCompare(right.name))
|
||||
.filter(entry => entry.name !== 'rules')
|
||||
.map(entry => createManagedOperation({
|
||||
moduleId: module.id,
|
||||
sourceRelativePath: path.join('.cursor', entry.name),
|
||||
destinationPath: path.join(targetRoot, entry.name),
|
||||
strategy: 'preserve-relative-path',
|
||||
}));
|
||||
|
||||
const ruleOperations = createFlatRuleOperations({
|
||||
moduleId: module.id,
|
||||
repoRoot,
|
||||
sourceRelativePath: '.cursor/rules',
|
||||
destinationDir: path.join(targetRoot, 'rules'),
|
||||
destinationNameTransform: toCursorRuleFileName,
|
||||
});
|
||||
|
||||
return takeUniqueOperations([...childOperations, ...ruleOperations]);
|
||||
}
|
||||
|
||||
return takeUniqueOperations([
|
||||
adapter.createScaffoldOperation(module.id, sourceRelativePath, planningInput),
|
||||
]);
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
@@ -181,7 +181,13 @@ function createNamespacedFlatRuleOperations(adapter, moduleId, sourceRelativePat
|
||||
return operations;
|
||||
}
|
||||
|
||||
function createFlatRuleOperations({ moduleId, repoRoot, sourceRelativePath, destinationDir }) {
|
||||
function createFlatRuleOperations({
|
||||
moduleId,
|
||||
repoRoot,
|
||||
sourceRelativePath,
|
||||
destinationDir,
|
||||
destinationNameTransform,
|
||||
}) {
|
||||
const normalizedSourcePath = normalizeRelativePath(sourceRelativePath);
|
||||
const sourceRoot = path.join(repoRoot || '', normalizedSourcePath);
|
||||
|
||||
@@ -201,19 +207,33 @@ function createFlatRuleOperations({ moduleId, repoRoot, sourceRelativePath, dest
|
||||
if (entry.isDirectory()) {
|
||||
const relativeFiles = listRelativeFiles(entryPath);
|
||||
for (const relativeFile of relativeFiles) {
|
||||
const flattenedFileName = `${namespace}-${normalizeRelativePath(relativeFile).replace(/\//g, '-')}`;
|
||||
const defaultFileName = `${namespace}-${normalizeRelativePath(relativeFile).replace(/\//g, '-')}`;
|
||||
const sourceRelativeFile = path.join(normalizedSourcePath, namespace, relativeFile);
|
||||
const flattenedFileName = typeof destinationNameTransform === 'function'
|
||||
? destinationNameTransform(defaultFileName, sourceRelativeFile)
|
||||
: defaultFileName;
|
||||
if (!flattenedFileName) {
|
||||
continue;
|
||||
}
|
||||
operations.push(createManagedOperation({
|
||||
moduleId,
|
||||
sourceRelativePath: path.join(normalizedSourcePath, namespace, relativeFile),
|
||||
sourceRelativePath: sourceRelativeFile,
|
||||
destinationPath: path.join(destinationDir, flattenedFileName),
|
||||
strategy: 'flatten-copy',
|
||||
}));
|
||||
}
|
||||
} else if (entry.isFile()) {
|
||||
const sourceRelativeFile = path.join(normalizedSourcePath, entry.name);
|
||||
const destinationFileName = typeof destinationNameTransform === 'function'
|
||||
? destinationNameTransform(entry.name, sourceRelativeFile)
|
||||
: entry.name;
|
||||
if (!destinationFileName) {
|
||||
continue;
|
||||
}
|
||||
operations.push(createManagedOperation({
|
||||
moduleId,
|
||||
sourceRelativePath: path.join(normalizedSourcePath, entry.name),
|
||||
destinationPath: path.join(destinationDir, entry.name),
|
||||
sourceRelativePath: sourceRelativeFile,
|
||||
destinationPath: path.join(destinationDir, destinationFileName),
|
||||
strategy: 'flatten-copy',
|
||||
}));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user