mirror of
https://github.com/storytold/designcraft.git
synced 2026-10-27 19:56:51 -06:00
fix(engine): Keep section prefixes to InDesign's rules
A section prefix is at most eight characters and contains no plus or comma (page references and ranges use them); `layout.section` refuses others and leaves the section unchanged. Symbols, a footnote style, no longer number pages. The parameter documentation lists the 01, 001 and 0001 styles, and a test pins the fields the generated dialogs read from both numbering commands. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
f061be9b3c
commit
498e3d401c
@@ -385,7 +385,7 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
"Numbering & Section Options…",
|
||||
["Layout"],
|
||||
None,
|
||||
"{page (1-based; starts a section there), startNumber?: n|null (continue), style?: arabic|upperRoman|lowerRoman|upperLetters|lowerLetters, prefix?, includePrefix?, marker?, remove?: bool}",
|
||||
"{page (1-based; starts a section there), startNumber?: n|null (continue), style?: arabic|upperRoman|lowerRoman|upperLetters|lowerLetters|arabicLeadingZero|arabicThreeDigits|arabicFourDigits, prefix? (up to 8 characters; no + or comma), includePrefix?, marker?, remove?: bool}",
|
||||
has_doc,
|
||||
|s, p| {
|
||||
let page = p.get("page").and_then(Value::as_u64).ok_or_else(|| bad("layout.section", "missing page"))? as usize;
|
||||
@@ -394,6 +394,11 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
return Err(bad("layout.section", format!("no page {page}")));
|
||||
}
|
||||
let start = page - 1;
|
||||
if let Some(prefix) = p.get("prefix").and_then(Value::as_str)
|
||||
&& (prefix.chars().count() > 8 || prefix.contains(['+', ',']))
|
||||
{
|
||||
return Err(bad("layout.section", "section prefix: up to 8 characters, without + or ,"));
|
||||
}
|
||||
let p = p.clone();
|
||||
s.edit(|d, _| {
|
||||
d.sections.retain(|x| x.start != start || start == 0);
|
||||
@@ -414,7 +419,11 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
None => {}
|
||||
}
|
||||
if let Some(v) = p.get("style") {
|
||||
sec.style = serde_json::from_value(v.clone()).map_err(|e| bad("layout.section", e.to_string()))?;
|
||||
sec.style = match serde_json::from_value(v.clone()) {
|
||||
Ok(designcraft_doc::NumberStyle::Symbols) => return Err(bad("layout.section", "symbols don't number pages")),
|
||||
Ok(style) => style,
|
||||
Err(e) => return Err(bad("layout.section", e.to_string())),
|
||||
};
|
||||
}
|
||||
if let Some(v) = p.get("prefix").and_then(Value::as_str) {
|
||||
sec.prefix = v.into();
|
||||
@@ -986,6 +995,20 @@ mod page_numbering_view_tests {
|
||||
assert_eq!(s.resolve_page("1"), Some(0));
|
||||
assert_eq!(s.resolve_page("9"), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn section_prefixes_are_short_and_avoid_plus_and_comma() {
|
||||
let mut s = crate::Session::new();
|
||||
s.execute("file.new", &json!({"pages": 2})).unwrap();
|
||||
for prefix in ["A-", "Appendix", "§ 1"] {
|
||||
s.execute("layout.section", &json!({"page": 2, "prefix": prefix})).unwrap();
|
||||
}
|
||||
for prefix in ["Appendix1", "A+", "1,2"] {
|
||||
assert!(s.execute("layout.section", &json!({"page": 2, "prefix": prefix})).is_err(), "{prefix}");
|
||||
}
|
||||
assert!(s.execute("layout.section", &json!({"page": 2, "style": "symbols"})).is_err());
|
||||
assert_eq!(s.doc().unwrap().doc.sections.iter().find(|x| x.start == 1).unwrap().prefix, "§ 1", "a refused prefix changes nothing");
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -4104,6 +4104,13 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn numbering_commands_document_their_fields() {
|
||||
let names = |id: &str| command_fields(designcraft_engine::find_command(id).unwrap().params).into_iter().map(|f| f.key).collect::<Vec<_>>();
|
||||
assert_eq!(names("layout.section"), ["page", "startNumber", "style", "prefix", "includePrefix", "marker", "remove"]);
|
||||
assert_eq!(names("layout.chapterNumbering"), ["style", "start", "source"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generic_command_preserves_array_geometry() {
|
||||
let mut app = command_app("file.new", json!({}));
|
||||
|
||||
Reference in New Issue
Block a user