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…**.
|
/// 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 {
|
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() {
|
if let Ok(exe_path) = std::env::current_exe() {
|
||||||
// The templates are at the project root level, same as Cargo.toml
|
// 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
|
// 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
|
// If we can't find the bundled template, panic with a clear error
|
||||||
dirs::home_dir()
|
// The bundled template should always be present in a properly built release
|
||||||
.unwrap_or_else(|| PathBuf::from("."))
|
panic!("Bundled template not found. Please ensure templates/snowflake/ exists relative to the executable.");
|
||||||
.join("Documents")
|
|
||||||
.join("Cookiecutters")
|
|
||||||
.join("snowflake")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Default subfolder opened after generating a project: the snowflake
|
/// Default subfolder opened after generating a project: the snowflake
|
||||||
/// template's drafting folder, where the chapter files live.
|
/// template's drafting folder (05-First Draft), where the chapter files live.
|
||||||
/// Supports both "05-First Draft" (merged planning+draft) and "06-First Draft" (legacy).
|
/// Contains merged planning and draft content in a single folder.
|
||||||
pub fn default_project_open_subdir() -> String {
|
pub fn default_project_open_subdir() -> String {
|
||||||
"05-First Draft".to_string()
|
"05-First Draft".to_string()
|
||||||
}
|
}
|
||||||
@@ -594,7 +591,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn bundled_template_is_found_via_exe_path() {
|
fn bundled_template_is_found_via_exe_path() {
|
||||||
let path = default_project_template();
|
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
|
// Verify it returns a valid path that contains cookiecutter.json
|
||||||
assert!(path.join("cookiecutter.json").is_file(),
|
assert!(path.join("cookiecutter.json").is_file(),
|
||||||
"Template path {} should contain cookiecutter.json", path.display());
|
"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("archive", "ARCHIVE"));
|
assert!(dir_matches("archive", "ARCHIVE"));
|
||||||
assert!(dir_matches("03-Characters", "Characters"));
|
assert!(dir_matches("03-Characters", "Characters"));
|
||||||
assert!(dir_matches("06-First Draft", "06-First Draft"));
|
assert!(dir_matches("05-First Draft", "05-First Draft"));
|
||||||
assert!(dir_matches("06-First Draft", "First Draft"));
|
assert!(dir_matches("05-First Draft", "First Draft"));
|
||||||
assert!(dir_matches("6 First Draft", "First Draft"));
|
assert!(dir_matches("5 First Draft", "First Draft"));
|
||||||
assert!(dir_matches("06_First Draft", "First Draft"));
|
assert!(dir_matches("05_First Draft", "First Draft"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -597,7 +597,7 @@ mod tests {
|
|||||||
let ws = scratch(
|
let ws = scratch(
|
||||||
"hidden",
|
"hidden",
|
||||||
&[
|
&[
|
||||||
"06-First Draft/ch-01.md",
|
"05-First Draft/ch-01.md",
|
||||||
"03-Characters/ada.md",
|
"03-Characters/ada.md",
|
||||||
"10-Archive/old/dead-draft.md",
|
"10-Archive/old/dead-draft.md",
|
||||||
"10-Archive/also-dead.md",
|
"10-Archive/also-dead.md",
|
||||||
@@ -609,7 +609,7 @@ mod tests {
|
|||||||
let hidden = vec!["Archive".to_string()];
|
let hidden = vec!["Archive".to_string()];
|
||||||
let mut kept = list_markdown_files(&ws, &hidden);
|
let mut kept = list_markdown_files(&ws, &hidden);
|
||||||
kept.sort();
|
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);
|
let _ = std::fs::remove_dir_all(&ws);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -624,16 +624,16 @@ mod tests {
|
|||||||
fn the_manuscript_folder_is_found_by_role_name() {
|
fn the_manuscript_folder_is_found_by_role_name() {
|
||||||
let ws = scratch(
|
let ws = scratch(
|
||||||
"project",
|
"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.
|
// The configured name matches with or without its number.
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
child_dir_matching(&ws, "06-First Draft").as_deref(),
|
child_dir_matching(&ws, "05-First Draft").as_deref(),
|
||||||
Some("06-First Draft")
|
Some("05-First Draft")
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
child_dir_matching(&ws, "First Draft").as_deref(),
|
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.
|
// A folder the project does not have is not invented.
|
||||||
assert_eq!(child_dir_matching(&ws, "09-Covers"), None);
|
assert_eq!(child_dir_matching(&ws, "09-Covers"), None);
|
||||||
@@ -646,7 +646,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn a_plain_chapter_folder_is_not_a_project_root() {
|
fn a_plain_chapter_folder_is_not_a_project_root() {
|
||||||
let ws = scratch("plain", &["ch-01.md", "ch-02.md"]);
|
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);
|
let _ = std::fs::remove_dir_all(&ws);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user