File › New: personal templates from a user templates folder (#2852) (#3133)

* #2852: personal templates in File › New, Save as Word Template

File › New lists the .dotx/.dotm files in the user templates folder under
Personal (a subfolder per category, search covers them); a click makes an
untitled document attached to the template. Save As › Save as Word Template
starts in that folder (<settings>/Templates, made on first use; File ›
Options › Advanced › File locations › User templates overrides it).
Engine: file.listTemplates (bounded, network folders refused, read root
applies), file.newFromTemplate sets the attached template, file.options
userTemplatesFolder, file.saveTemplate keeps a .dotm name. UI:
ui.saveAsTemplate; Save dialog requests carry a start folder.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012WEhZXSxzS8orX7f9J3qpr

* #2852: review — a personal template asks about unsaved changes; network templates folder refused before it's looked at; New lists the folder once per visit with Refresh; .dotx/.dotm labels alike

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012WEhZXSxzS8orX7f9J3qpr

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: aiongg <aiongtaigi@gmail.com>
This commit is contained in:
Martin Ball
2026-10-21 20:18:50 -04:00
committed by GitHub
co-authored by Claude Opus 5.5 aiongg
parent dbebb2eca7
commit 5a6d2b6070
44 changed files with 1261 additions and 50 deletions
+6 -3
View File
@@ -489,17 +489,20 @@ pub fn specs() -> Vec<CommandSpec> {
.pure(),
CommandSpec::new("file.newFromTemplate", "New from Template", "File › New", |s, v| {
let path = p::req_str(v, "path")?;
let doc = crate::io::open_path(std::path::Path::new(path)).map_err(CmdError::Failed)?;
let mut doc = crate::io::open_path(std::path::Path::new(path)).map_err(CmdError::Failed)?;
// As in Word, the new document is attached to the template it came from (#2852).
doc.settings.attached_template = Some(path.to_string());
s.set_document(doc);
s.path = None;
s.dirty = true;
sel_result(s)
})
.params(r#"{"path": string}"#)
.params(r#"{"path": string} → a new, untitled document from the template, attached to it"#)
.pure(),
CommandSpec::new("file.saveTemplate", "Save as Template", "File › Save As", |s, v| {
let path = p::req_str(v, "path")?;
let path = if path.ends_with(".dotx") { path.to_string() } else { format!("{path}.dotx") };
// A .dotm keeps its name (#2852); anything else becomes a .dotx.
let path = if super::user_templates::is_template_name(path) { path.to_string() } else { format!("{path}.dotx") };
crate::io::save_path(std::path::Path::new(&path), &s.doc).map_err(CmdError::Failed)?;
Ok(json!({"path": path}))
})