[CC3] table.cellAlign takes a horizontal align

align: left|center|right|justify sets every paragraph of the target cells;
anchor stays the vertical alignment and is optional when align is given.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Zach BerryandClaude Sonnet 5.5 committed 2026-10-27 20:31:46 -05:00
1 parent 55e5ee56b4
commit f58ec39968
2 files changed
+56 -8

No files matched your search

+33 -8
View File
@@ -108,7 +108,7 @@ pub fn specs() -> Vec<CommandSpec> {
"Align Cell Text",
["Table Layout", "Alignment"],
None,
"{anchor: top|middle|bottom, cells?, id?}",
"{anchor?: top|middle|bottom (vertical; top when neither anchor nor align is given), align?: left|center|right|justify (horizontal, applied to every paragraph of the cells), cells?, id?}",
has_selection,
cell_align
),
@@ -535,18 +535,43 @@ fn cell_margins(s: &mut Session, p: &Value) -> Result<Value> {
}
fn cell_align(s: &mut Session, p: &Value) -> Result<Value> {
use deckcraft_model::text::Anchor;
let a = match str_param(p, "anchor").unwrap_or("top") {
"middle" | "center" | "ctr" => Anchor::Middle,
"bottom" | "b" => Anchor::Bottom,
"top" | "t" => Anchor::Top,
o => return Err(bad("table.cellAlign", format!("unknown anchor {o:?}; one of top, middle, bottom"))),
use deckcraft_model::text::{Align, Anchor};
// A value that is not a string is refused, not taken as absent.
for k in ["align", "anchor"] {
if p.get(k).is_some_and(|v| !v.is_null() && !v.is_string()) {
return Err(bad("table.cellAlign", format!("`{k}` is a name such as {}", if k == "align" { "left or center" } else { "top or middle" })));
}
}
// Without `align`, the vertical anchor is the whole command (top when not given).
let align = match str_param(p, "align") {
None => None,
Some("left" | "l") => Some(Align::Left),
Some("center" | "centre" | "ctr") => Some(Align::Center),
Some("right" | "r") => Some(Align::Right),
Some("justify" | "just") => Some(Align::Justify),
Some(o) => return Err(bad("table.cellAlign", format!("unknown align {o:?}; one of left, center, right, justify"))),
};
let anchor = match (str_param(p, "anchor"), align) {
(None, Some(_)) => None,
(a, _) => Some(match a.unwrap_or("top") {
"middle" | "center" | "ctr" => Anchor::Middle,
"bottom" | "b" => Anchor::Bottom,
"top" | "t" => Anchor::Top,
o => return Err(bad("table.cellAlign", format!("unknown anchor {o:?}; one of top, middle, bottom"))),
}),
};
let targets = target_cells(s, p)?;
with_table(s, p, "table.cellAlign", move |t| {
for (r, c) in targets(t) {
if let Some(cell) = t.cell_mut(r, c) {
cell.anchor = Some(a);
if anchor.is_some() {
cell.anchor = anchor;
}
if let Some(a) = align {
for para in &mut cell.text.paragraphs {
para.props.align = Some(a);
}
}
}
}
Ok(())
+23
View File
@@ -5646,3 +5646,26 @@ fn invalid_ids_array_never_falls_back_to_the_selection() {
assert!(s.doc().unwrap().shape(deckcraft_model::ShapeId(a as u32)).is_some(), "shape deleted for {ids}");
}
}
#[test]
fn table_cell_align_sets_the_horizontal_alignment() {
use deckcraft_model::text::{Align, Anchor};
let mut s = session();
let id = table_at(&mut s, &[100.0, 100.0], json!([["a", "b"], ["c", "d"]]));
s.execute("table.cellAlign", &json!({"id": id.0, "align": "center", "cells": [[0, 0], [1, 0]]})).unwrap();
s.execute("table.cellAlign", &json!({"id": id.0, "align": "right", "anchor": "bottom", "cells": [[0, 1]]})).unwrap();
let t = table_of(&s, id);
let al = |r, c| t.cell(r, c).unwrap().text.paragraphs.iter().map(|p| p.props.align).collect::<Vec<_>>();
assert_eq!(al(0, 0), vec![Some(Align::Center)]);
assert_eq!(al(1, 0), vec![Some(Align::Center)]);
assert_eq!(al(0, 1), vec![Some(Align::Right)]);
assert_eq!(al(1, 1), vec![None], "other cells are untouched");
assert_eq!(t.cell(0, 1).unwrap().anchor, Some(Anchor::Bottom));
assert_eq!(t.cell(0, 0).unwrap().anchor, None, "align alone leaves the vertical anchor");
assert!(s.execute("table.cellAlign", &json!({"id": id.0, "align": "diagonal"})).is_err());
// A value that is not a name is refused, not read as absent (which would set the anchor to top).
let rev = s.doc().unwrap().revision;
assert!(s.execute("table.cellAlign", &json!({"id": id.0, "align": 1})).is_err());
assert!(s.execute("table.cellAlign", &json!({"id": id.0, "align": "left", "anchor": true})).is_err());
assert_eq!(s.doc().unwrap().revision, rev);
}