M3: variables.define refuses a text that is neither a string, a number nor a boolean (#2093)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Trevor BrownandClaude Fable 5.1 committed 2026-11-02 04:13:40 -05:00
1 parent 485a94673f
commit 5de0a0b806
3 files changed
+16 -3

No files matched your search

+9 -2
View File
@@ -28,7 +28,7 @@ pub fn specs() -> Vec<CommandSpec> {
"Define Text Variable…",
["Type", "Text Variables"],
None,
"{name, type: custom|lastPageNumber|chapterNumber|fileName|creationDate|modificationDate|outputDate|runningHeader, text? (a string; a number is shown as its digits), format?, style?, use?: firstOnPage|lastOnPage, character?, section?, extension?, before?, after?} — creates or replaces by name",
"{name, type: custom|lastPageNumber|chapterNumber|fileName|creationDate|modificationDate|outputDate|runningHeader, text? (a string; a number or a boolean is shown as typed, anything else is refused), format?, style?, use?: firstOnPage|lastOnPage, character?, section?, extension?, before?, after?} — creates or replaces by name",
has_doc,
define
),
@@ -407,7 +407,14 @@ fn define(s: &mut Session, p: &Value) -> Result<Value> {
let name = str_param(p, "name").ok_or_else(|| bad("variables.define", "missing name"))?.to_string();
let fmt = || str_param(p, "format").unwrap_or("MM/dd/yy").to_string();
let kind = match str_param(p, "type").unwrap_or("custom") {
"custom" => VarKind::Custom { text: text_param(p, "text").unwrap_or_default() },
"custom" => VarKind::Custom {
// No `text` is empty text; an object or an array is refused rather than stored as
// empty text in place of what a variable of that name holds.
text: match p.get("text") {
None | Some(Value::Null) => String::new(),
Some(_) => text_param(p, "text").ok_or_else(|| bad("variables.define", "`text` must be a string, a number or a boolean"))?,
},
},
"lastPageNumber" => VarKind::LastPageNumber { section: p.get("section").and_then(Value::as_bool).unwrap_or(false) },
"chapterNumber" => VarKind::ChapterNumber,
"fileName" => VarKind::FileName { extension: p.get("extension").and_then(Value::as_bool).unwrap_or(false) },
+6
View File
@@ -444,9 +444,15 @@ fn a_custom_variable_defined_with_a_number_shows_its_digits() {
s.execute("variables.define", &json!({"name": "Year", "type": "custom", "text": 2026})).unwrap();
s.execute("variables.define", &json!({"name": "Half", "type": "custom", "text": 0.5})).unwrap();
s.execute("variables.define", &json!({"name": "Word", "type": "custom", "text": "year"})).unwrap();
s.execute("variables.define", &json!({"name": "Flag", "type": "custom", "text": true})).unwrap();
// Anything else is refused, and a variable of that name keeps its text; no text is empty text.
assert!(s.execute("variables.define", &json!({"name": "Year", "type": "custom", "text": {"y": 2026}})).is_err());
assert!(s.execute("variables.define", &json!({"name": "Year", "type": "custom", "text": [2026]})).is_err());
s.execute("variables.define", &json!({"name": "Blank", "type": "custom"})).unwrap();
let list = s.execute("variables.list", &json!({})).unwrap();
let value = |name: &str| list.as_array().unwrap().iter().find(|v| v["name"] == name).unwrap()["value"].as_str().unwrap().to_string();
assert_eq!((value("Year"), value("Half"), value("Word")), ("2026".to_string(), "0.5".to_string(), "year".to_string()));
assert_eq!((value("Flag"), value("Blank")), ("true".to_string(), String::new()));
// Inserted into a story, the instance composes as four digits.
let r = s.execute("frame.create", &json!({"rect": [72, 72, 400, 300], "content": "text", "text": ""})).unwrap();
let sid = s.doc().unwrap().doc.item(designcraft_doc::ItemId(r["id"].as_u64().unwrap())).unwrap().text_frame().unwrap().story;
+1 -1
View File
@@ -48,7 +48,7 @@ basics of editing fail for too many users on Windows and Linux.
| Numeric fields: units, arithmetic, scrubbing | ✓ | 21 pt spinner fields with arithmetic | ✓ | |
| Colour fields: hex, picker from any swatch field | ✓ | ✓ | ~ | hex entry and picker issues (#323, #190) |
| Panels: Pages, Layers, Swatches, Color, Stroke, Character, Paragraph, Styles, Links, Effects, Text Wrap, Align, Pathfinder, Table, Index, TOC, Hyperlinks, Bookmarks, Articles, Tags, Notes, Track Changes, Object States, Buttons and Forms, Preflight, Data Merge, Library, Scripts, Glyphs, Info, Tabs, Story | ✓ | all present | ~ | Navigator, Trap Presets, Animation, Timing missing; pull-down panels can't scroll on Linux (#267) |
| Dialogs: New Document, Document Setup, Preferences (all pages), Paragraph/Character/Object/Table/Cell Style Options, Export PDF, Print, Package, Find/Change | ✓ | present | ~ | a Custom text variable whose text is typed as a number shows its digits (`variables.define` takes a string or a number for `text`; #2093); generated command dialogs fill the long tail; depth varies |
| Dialogs: New Document, Document Setup, Preferences (all pages), Paragraph/Character/Object/Table/Cell Style Options, Export PDF, Print, Package, Find/Change | ✓ | present | ~ | a Custom text variable whose text is typed as a number shows its digits (`variables.define` takes a string, a number or a boolean for `text` and refuses anything else; #2093); generated command dialogs fill the long tail; depth varies |
| Workspaces | Essentials, Essentials Classic, Advanced, Book, Digital Publishing, Interactive for PDF, Printing and Proofing, Review, Typography, Touch | ✓ named workspaces (Essentials Classic: Control panel and iconic panel groups) + custom; Window › Workspace; no Review or Touch | ~ | tab bar overlaps menus in Book/Advanced (#182) |
| Story Editor | ✓ | ✓ | ~ | depth ruler and View › Story Editor › Show/Hide Depth Ruler (`story_editor.rs` `depth_ruler_shows_and_hides_from_the_view_menu`); hiding or resizing the style-name column missing |
| Undo granularity (a drag = one step) | ✓ | ✓ (Begin/Preview/Commit) | ✓ | |