chore: bump cursor_templates_version to 1.0.4 and update related files
- Updated cursor_templates_version in project-brief.yaml to 1.0.4 for reproducibility. - Enhanced CHANGELOG with fixes and features for version 1.0.4, including improved template resolution for global installs. - Updated pubspec.yaml and VERSION file to reflect the new version. - Added new templates for AGENTS.md and lefthook.yaml to the generator. - Adjusted tests to include new root-level files in the output. This release addresses template resolution issues and introduces new repo-level configuration files.
This commit is contained in:
@@ -130,8 +130,7 @@ Future<void> main(List<String> arguments) async {
|
||||
final templateFiles = Resolver.resolve(brief);
|
||||
Logger.info('Resolved ${templateFiles.length} template files');
|
||||
|
||||
final templateDir =
|
||||
templateSrc.isEmpty ? await _defaultTemplateDir() : templateSrc;
|
||||
final templateDir = await _resolveTemplateDir(templateSrc);
|
||||
final rendered = await Renderer.render(
|
||||
brief: brief,
|
||||
templateFiles: templateFiles,
|
||||
@@ -147,7 +146,12 @@ Future<void> main(List<String> arguments) async {
|
||||
outputDir: outputDir,
|
||||
templateFiles: templateFiles);
|
||||
|
||||
Logger.success('\n✔ Done! ${rendered.length} files written to $outputDir/');
|
||||
final underCursor =
|
||||
rendered.keys.where((k) => !k.startsWith('__root__/')).length;
|
||||
final atRoot = rendered.length - underCursor;
|
||||
Logger.success(
|
||||
'\n✔ Done! $underCursor file(s) under $outputDir/'
|
||||
'${atRoot > 0 ? ", $atRoot at project root" : ""}.');
|
||||
if (overrideSnapshot.customFiles.isNotEmpty) {
|
||||
Logger.success(
|
||||
' ↳ ${overrideSnapshot.customFiles.length} custom override(s) preserved untouched');
|
||||
@@ -162,12 +166,11 @@ Future<void> _runDiff(
|
||||
final rendered = await Renderer.render(
|
||||
brief: brief,
|
||||
templateFiles: templateFiles,
|
||||
templateSrc:
|
||||
templateSrc.isEmpty ? await _defaultTemplateDir() : templateSrc,
|
||||
templateSrc: await _resolveTemplateDir(templateSrc),
|
||||
);
|
||||
Logger.info('Diff preview (no files written):\n');
|
||||
for (final entry in rendered.entries) {
|
||||
final existing = File('$outputDir/${entry.key}');
|
||||
final existing = File(_resolvedOutputPath(outputDir, entry.key));
|
||||
if (!existing.existsSync()) {
|
||||
Logger.success(' + ${entry.key}');
|
||||
} else {
|
||||
@@ -187,7 +190,7 @@ Future<void> _writeOutput(
|
||||
bool isRefresh,
|
||||
) async {
|
||||
for (final entry in rendered.entries) {
|
||||
final file = File('$outputDir/${entry.key}');
|
||||
final file = File(_resolvedOutputPath(outputDir, entry.key));
|
||||
await file.parent.create(recursive: true);
|
||||
if (isRefresh && file.existsSync()) {
|
||||
final merged = OverrideManager.mergeCustomSections(
|
||||
@@ -210,27 +213,71 @@ Future<void> _writeMetadataJson(String outputDir, ProjectBrief brief) async {
|
||||
await file.writeAsString(encoder.convert(brief.toMetadataMap()));
|
||||
}
|
||||
|
||||
Future<String> _defaultTemplateDir() async {
|
||||
const _templateSentinel = 'rules/universal/flutter-core.mdc.tmpl';
|
||||
|
||||
Future<String> _resolveTemplateDir(String override) async {
|
||||
if (override.isNotEmpty) {
|
||||
final dir = p.normalize(override);
|
||||
_assertTemplateBundle(dir);
|
||||
return dir;
|
||||
}
|
||||
final tried = <String>[];
|
||||
for (final dir in await _templateDirCandidates()) {
|
||||
tried.add(dir);
|
||||
if (File(p.join(dir, _templateSentinel)).existsSync()) return dir;
|
||||
}
|
||||
Logger.error('cursor_gen: No template bundle found (missing $_templateSentinel). Tried:');
|
||||
for (final t in tried) Logger.error(' • $t');
|
||||
Logger.error(
|
||||
'Use: cursor_gen --templates /path/to/cursor_gen/templates (folder containing rules/, hooks/, …)');
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void _assertTemplateBundle(String dir) {
|
||||
if (!File(p.join(dir, _templateSentinel)).existsSync()) {
|
||||
Logger.error('Invalid template directory: $dir ($_templateSentinel not found)');
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<String>> _templateDirCandidates() async {
|
||||
final binDir = p.dirname(Platform.script.toFilePath());
|
||||
final candidates = <String>[
|
||||
// Monorepo layout: flutter-cursor-templates/generator/bin -> ../templates.
|
||||
p.normalize(p.join(binDir, '..', '..', 'templates')),
|
||||
// Published package layout: cursor_gen/templates.
|
||||
p.normalize(p.join(binDir, '..', 'templates')),
|
||||
];
|
||||
final out = <String>[];
|
||||
|
||||
final packageUri = await Isolate.resolvePackageUri(
|
||||
Uri.parse('package:cursor_gen/src/renderer.dart'),
|
||||
);
|
||||
if (packageUri != null && packageUri.isScheme('file')) {
|
||||
final packageRoot = p.dirname(p.dirname(packageUri.toFilePath()));
|
||||
candidates.add(p.normalize(p.join(packageRoot, 'templates')));
|
||||
final packageRoot = _packageRootDir(packageUri.toFilePath());
|
||||
if (packageRoot.isNotEmpty) {
|
||||
out.add(p.normalize(p.join(packageRoot, 'templates')));
|
||||
}
|
||||
}
|
||||
// Published layout: <package>/templates next to bin/
|
||||
out.add(p.normalize(p.join(binDir, '..', 'templates')));
|
||||
// Monorepo: flutter-cursor-templates/templates
|
||||
out.add(p.normalize(p.join(binDir, '..', '..', 'templates')));
|
||||
|
||||
return candidates.firstWhere(
|
||||
(path) => Directory(path).existsSync(),
|
||||
orElse: () => candidates.last,
|
||||
);
|
||||
return out;
|
||||
}
|
||||
|
||||
/// From e.g. `.../cursor_gen-1.0.3/lib/src/renderer.dart`, walk up to the directory that contains `pubspec.yaml`.
|
||||
String _packageRootDir(String resolvedLibFile) {
|
||||
var dir = p.dirname(resolvedLibFile);
|
||||
while (true) {
|
||||
if (File(p.join(dir, 'pubspec.yaml')).existsSync()) return dir;
|
||||
final parent = p.dirname(dir);
|
||||
if (parent == dir) return '';
|
||||
dir = parent;
|
||||
}
|
||||
}
|
||||
|
||||
String _resolvedOutputPath(String outputDir, String relativeKey) {
|
||||
if (relativeKey.startsWith('__root__/')) {
|
||||
final name = relativeKey.substring('__root__/'.length);
|
||||
return p.normalize(p.join(p.dirname(p.absolute(outputDir)), name));
|
||||
}
|
||||
return p.normalize(p.join(p.absolute(outputDir), relativeKey));
|
||||
}
|
||||
|
||||
void _printBanner() {
|
||||
|
||||
Reference in New Issue
Block a user