Text: layer.setText's schema accepts discretionaryLigatures and ss01–ss20 under checked execution (#521 follow-up)

The params parser reads ':' as the start of a value, so 'OpenType?:
discretionaryLigatures?' declared a bogus OpenType key and hid
discretionaryLigatures, and 'ss01?…ss20?' declared only ss01.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01QiAJeFttZp83Fh7YuzAR5f
This commit is contained in:
Claude committed 2026-10-10 12:58:15 +00:00
1 parent 9308d8e0f0
commit 195b862036
2 files changed
+17 -1

No files matched your search

+1 -1
View File
@@ -1548,7 +1548,7 @@ pub fn specs() -> Vec<CommandSpec> {
"Edit Text",
[],
None,
"{layer?, range?: [start, end] (characters; default all), text?, font?, style?, size?, fill?, stroke?, applyFill?, applyStroke?, strokeWidth?, tracking?, leading?: px|\"auto\", baselineShift? px, hScale? %, vScale? %, tsume? %, fauxBold?, fauxItalic?, allCaps?, smallCaps?, baseline?: normal|superscript|subscript, superscript?, subscript?, kerning?: metrics|optical|number, ligatures?, OpenType?: discretionaryLigatures?, contextualAlternates?, stylisticAlternates?, stylisticSets?: [1–20], ss01?…ss20?, swash?, titling?, ordinals?, fractions?, allSmallCaps?, figureStyle?: default|lining|oldStyle, figureWidth?: default|proportional|tabular, figures?, variations?: {tag: value} (variable font axes; null resets), justify?: left|center|right|justifyLeft|justifyCenter|justifyRight|justifyAll, indentLeft?, indentRight?, indentFirst?, spaceBefore?, spaceAfter?, direction?: ltr|rtl, composer?: everyLine|singleLine, hangingPunctuation?, strokeOverFill?, box?: [x,y,w,h]|null (layer space), vertical?}",
"{layer?, range?: [start, end] (characters; default all), text?, font?, style?, size?, fill?, stroke?, applyFill?, applyStroke?, strokeWidth?, tracking?, leading?: px|\"auto\", baselineShift? px, hScale? %, vScale? %, tsume? %, fauxBold?, fauxItalic?, allCaps?, smallCaps?, baseline?: normal|superscript|subscript, superscript?, subscript?, kerning?: metrics|optical|number, ligatures?, discretionaryLigatures? (OpenType), contextualAlternates?, stylisticAlternates?, stylisticSets?: [1–20], ss01?, ss02?, ss03?, ss04?, ss05?, ss06?, ss07?, ss08?, ss09?, ss10?, ss11?, ss12?, ss13?, ss14?, ss15?, ss16?, ss17?, ss18?, ss19?, ss20?, swash?, titling?, ordinals?, fractions?, allSmallCaps?, figureStyle?: default|lining|oldStyle, figureWidth?: default|proportional|tabular, figures?, variations?: {tag: value} (variable font axes; null resets), justify?: left|center|right|justifyLeft|justifyCenter|justifyRight|justifyAll, indentLeft?, indentRight?, indentFirst?, spaceBefore?, spaceAfter?, direction?: ltr|rtl, composer?: everyLine|singleLine, hangingPunctuation?, strokeOverFill?, box?: [x,y,w,h]|null (layer space), vertical?}",
has_layers,
set_text
),
+16
View File
@@ -259,3 +259,19 @@ fn fonts_lists_bundled_and_installed_families() {
assert_eq!(crate::font_styles("NOTO SERIF"), styles);
assert_eq!(crate::font_styles("No Such Family").len(), 5);
}
/// `layer.setText`'s schema lists every OpenType key as optional, so checked execution (control
/// channel, MCP) accepts them and requires none (#520).
#[test]
fn set_text_schema_accepts_every_opentype_key_and_requires_none() {
let spec = crate::commands::find("layer.setText").unwrap();
let schema = crate::commands::params_schema(spec);
assert_eq!(schema["required"], json!([]));
for key in ["discretionaryLigatures", "ss01", "ss02", "ss20", "swash"] {
assert!(schema["properties"].get(key).is_some(), "{key} is not in the schema");
}
assert!(schema["properties"].get("OpenType").is_none());
let (mut s, t) = session("Office 1/2");
s.execute_checked("layer.setText", json!({"layer": t, "discretionaryLigatures": true, "ss02": true, "ss20": true})).unwrap();
assert!(doc(&s, t).style_at(0).opentype.stylistic_set(20));
}