feat: Remove fallback to Cookiecutters, use bundled template only
- Remove fallback to ~/Documents/Cookiecutters/snowflake from default_project_template() - Panic with clear error if bundled template not found - Update tests to use 05-First Draft instead of 06-First Draft - Update comments to reflect merged structure (05-First Draft contains planning+draft) The code now only uses the bundled template at templates/snowflake/ relative to the executable, ensuring all new projects use the merged 05-First Draft structure. Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
This commit is contained in:
+8
-11
@@ -185,9 +185,9 @@ pub fn default_show_toolbar() -> bool {
|
||||
}
|
||||
|
||||
/// Default cookiecutter template for **File ▸ New project…**.
|
||||
/// First tries the bundled template, then falls back to the user's Cookiecutters directory.
|
||||
/// Uses the bundled template from the project's templates/snowflake directory.
|
||||
pub fn default_project_template() -> PathBuf {
|
||||
// Try the bundled template first (relative to the executable)
|
||||
// Find the bundled template relative to the executable's location
|
||||
if let Ok(exe_path) = std::env::current_exe() {
|
||||
// The templates are at the project root level, same as Cargo.toml
|
||||
// binary is typically at target/release/md-manuscript or target/debug/md-manuscript
|
||||
@@ -209,17 +209,14 @@ pub fn default_project_template() -> PathBuf {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Fallback to user's Cookiecutters directory
|
||||
dirs::home_dir()
|
||||
.unwrap_or_else(|| PathBuf::from("."))
|
||||
.join("Documents")
|
||||
.join("Cookiecutters")
|
||||
.join("snowflake")
|
||||
// If we can't find the bundled template, panic with a clear error
|
||||
// The bundled template should always be present in a properly built release
|
||||
panic!("Bundled template not found. Please ensure templates/snowflake/ exists relative to the executable.");
|
||||
}
|
||||
|
||||
/// Default subfolder opened after generating a project: the snowflake
|
||||
/// template's drafting folder, where the chapter files live.
|
||||
/// Supports both "05-First Draft" (merged planning+draft) and "06-First Draft" (legacy).
|
||||
/// template's drafting folder (05-First Draft), where the chapter files live.
|
||||
/// Contains merged planning and draft content in a single folder.
|
||||
pub fn default_project_open_subdir() -> String {
|
||||
"05-First Draft".to_string()
|
||||
}
|
||||
@@ -594,7 +591,7 @@ mod tests {
|
||||
#[test]
|
||||
fn bundled_template_is_found_via_exe_path() {
|
||||
let path = default_project_template();
|
||||
// The function should find either the bundled template or the fallback
|
||||
// The function should find the bundled template
|
||||
// Verify it returns a valid path that contains cookiecutter.json
|
||||
assert!(path.join("cookiecutter.json").is_file(),
|
||||
"Template path {} should contain cookiecutter.json", path.display());
|
||||
|
||||
+11
-11
@@ -576,10 +576,10 @@ mod tests {
|
||||
assert!(dir_matches("Archive", "Archive"));
|
||||
assert!(dir_matches("archive", "ARCHIVE"));
|
||||
assert!(dir_matches("03-Characters", "Characters"));
|
||||
assert!(dir_matches("06-First Draft", "06-First Draft"));
|
||||
assert!(dir_matches("06-First Draft", "First Draft"));
|
||||
assert!(dir_matches("6 First Draft", "First Draft"));
|
||||
assert!(dir_matches("06_First Draft", "First Draft"));
|
||||
assert!(dir_matches("05-First Draft", "05-First Draft"));
|
||||
assert!(dir_matches("05-First Draft", "First Draft"));
|
||||
assert!(dir_matches("5 First Draft", "First Draft"));
|
||||
assert!(dir_matches("05_First Draft", "First Draft"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -597,7 +597,7 @@ mod tests {
|
||||
let ws = scratch(
|
||||
"hidden",
|
||||
&[
|
||||
"06-First Draft/ch-01.md",
|
||||
"05-First Draft/ch-01.md",
|
||||
"03-Characters/ada.md",
|
||||
"10-Archive/old/dead-draft.md",
|
||||
"10-Archive/also-dead.md",
|
||||
@@ -609,7 +609,7 @@ mod tests {
|
||||
let hidden = vec!["Archive".to_string()];
|
||||
let mut kept = list_markdown_files(&ws, &hidden);
|
||||
kept.sort();
|
||||
assert_eq!(kept, v(&["03-Characters/ada.md", "06-First Draft/ch-01.md"]));
|
||||
assert_eq!(kept, v(&["03-Characters/ada.md", "05-First Draft/ch-01.md"]));
|
||||
let _ = std::fs::remove_dir_all(&ws);
|
||||
}
|
||||
|
||||
@@ -624,16 +624,16 @@ mod tests {
|
||||
fn the_manuscript_folder_is_found_by_role_name() {
|
||||
let ws = scratch(
|
||||
"project",
|
||||
&["06-First Draft/ch-01.md", "03-Characters/ada.md"],
|
||||
&["05-First Draft/ch-01.md", "03-Characters/ada.md"],
|
||||
);
|
||||
// The configured name matches with or without its number.
|
||||
assert_eq!(
|
||||
child_dir_matching(&ws, "06-First Draft").as_deref(),
|
||||
Some("06-First Draft")
|
||||
child_dir_matching(&ws, "05-First Draft").as_deref(),
|
||||
Some("05-First Draft")
|
||||
);
|
||||
assert_eq!(
|
||||
child_dir_matching(&ws, "First Draft").as_deref(),
|
||||
Some("06-First Draft")
|
||||
Some("05-First Draft")
|
||||
);
|
||||
// A folder the project does not have is not invented.
|
||||
assert_eq!(child_dir_matching(&ws, "09-Covers"), None);
|
||||
@@ -646,7 +646,7 @@ mod tests {
|
||||
#[test]
|
||||
fn a_plain_chapter_folder_is_not_a_project_root() {
|
||||
let ws = scratch("plain", &["ch-01.md", "ch-02.md"]);
|
||||
assert_eq!(child_dir_matching(&ws, "06-First Draft"), None);
|
||||
assert_eq!(child_dir_matching(&ws, "05-First Draft"), None);
|
||||
let _ = std::fs::remove_dir_all(&ws);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user