Merge pull request #3951 from dotCooCoo/fix/layer-ids-refused-by-object-commands

Arrange: a layer id given to Send to Back and the other selection commands is refused
This commit is contained in:
BFlat
2026-10-24 19:00:42 +07:00
committed by GitHub
23 changed files with 138 additions and 0 deletions
+21
View File
@@ -1753,6 +1753,24 @@ impl Session {
r
}
/// Error, under the command's own id, at the first of `ids` that is malformed, names no node, or
/// names a layer or sublayer: a command in [`SELECTS_GIVEN_IDS`] acts on objects.
fn check_given_ids(&self, id: &str, params: &Value) -> Result<()> {
let (Some(st), Some(ids)) = (self.active(), params.get("ids")) else { return Ok(()) };
let Some(given) = ids.as_array() else { return cmd::checked_ids_param(self, params, "ids", id).map(drop) };
for value in given {
let node = cmd::checked_id(self, value, id)?;
if st.doc.node(node).is_some_and(|n| n.is_layer()) {
return Err(if id.starts_with("object.arrange.") {
cmd::bad(id, format!("id {value} is a layer, not an object; move layers with layer.move"))
} else {
cmd::bad(id, format!("id {value} is a layer, not an object"))
});
}
}
Ok(())
}
/// Execute a command by id. This is THE entry point for every frontend.
pub fn execute(&mut self, id: &str, params: &Value) -> Result<Value> {
let spec = find_command(id).ok_or_else(|| EngineError::UnknownCommand(id.to_string()))?;
@@ -1771,6 +1789,9 @@ impl Session {
if cmd::params::id_stands_for_ids(spec.params) && !effect_named && self.active().is_some() {
cmd::given_objects(self, params, id)?;
}
if SELECTS_GIVEN_IDS.contains(&id) {
self.check_given_ids(id, params)?;
}
// Clear's menu needs a selection; an agent supplying explicit targets only needs a
// document. The command validates those targets before making any edit.
let given = given_ids(spec.params, params);
@@ -143,6 +143,78 @@ fn bad_ids_are_refused_and_change_nothing() {
}
}
/// A layer or sublayer is not an object these commands act on: its id is refused, alone or with an
/// object's, and the document, the selection and the undo history stay as they were.
#[test]
fn layer_ids_are_refused_and_change_nothing() {
let (mut s, ids) = doc();
let layer = s.execute("layer.new", &json!({"name": "Top"})).unwrap()["id"].as_u64().unwrap();
let sub = s.execute("layer.newSublayer", &json!({"parent": layer})).unwrap()["id"].as_u64().unwrap();
s.execute("select.set", &json!({"ids": [ids[3]]})).unwrap();
let st = s.doc().unwrap();
let (before, undo) = (st.doc.clone(), st.history.undo.len());
let params = |cmd: &str| match cmd {
"edit.duplicate" => json!({"dx": 5, "dy": 5}),
"object.move" => json!({"dx": 12, "dy": -4}),
"object.rotate" => json!({"angle": 30}),
"object.scale" => json!({"sx": 150}),
"object.reflect" => json!({"axis": "vertical"}),
"object.shear" => json!({"angle": 20}),
_ => json!({}),
};
for cmd in SELECTS_GIVEN_IDS {
for given in [json!([layer]), json!([sub]), json!([ids[0], layer])] {
let mut p = params(cmd);
p["ids"] = given.clone();
let r = s.execute(cmd, &p);
let Err(EngineError::BadParams { msg, .. }) = &r else { panic!("{cmd} {given}: {r:?}") };
assert!(msg.contains("is a layer, not an object"), "{cmd} {given}: {msg}");
assert_eq!(msg.contains("layer.move"), cmd.starts_with("object.arrange."), "{cmd} {given}: {msg}");
let st = s.doc().unwrap();
assert!(st.doc == before, "{cmd} {given}: the document changed");
assert_eq!(st.selection.objects, vec![NodeId(ids[3])], "{cmd} {given}: the selection stays");
assert_eq!(st.history.undo.len(), undo, "{cmd} {given}: an undo step was recorded");
}
}
// An unknown id before the layer's is still reported as unknown.
let r = s.execute("object.arrange.sendToBack", &json!({"ids": [999, layer]}));
assert!(matches!(&r, Err(EngineError::BadParams { msg, .. }) if msg == "no such object id 999"), "{r:?}");
}
/// An id that names no object is reported by the command that was run, not by the `select.set`
/// that checks the ids.
#[test]
fn id_errors_name_the_command_run() {
let (mut s, ids) = doc();
let layer = s.execute("layer.new", &json!({"name": "Top"})).unwrap()["id"].as_u64().unwrap();
s.execute("select.set", &json!({"ids": [ids[3]]})).unwrap();
let before = s.doc().unwrap().doc.clone();
for cmd in SELECTS_GIVEN_IDS {
for (given, want) in [
(json!([999]), "no such object id 999".to_string()),
(json!([999, layer]), "no such object id 999".to_string()),
(json!([ids[0], ids[1], -1]), "invalid object id -1: expected a non-negative integer".to_string()),
(json!(ids[0]), "ids must be an array of non-negative integer object ids".to_string()),
] {
let mut p = match *cmd {
"edit.duplicate" => json!({"dx": 5, "dy": 5}),
"object.move" => json!({"dx": 12, "dy": -4}),
"object.rotate" => json!({"angle": 30}),
"object.scale" => json!({"sx": 150}),
"object.reflect" => json!({"axis": "vertical"}),
"object.shear" => json!({"angle": 20}),
_ => json!({}),
};
p["ids"] = given.clone();
let r = s.execute(cmd, &p);
let Err(EngineError::BadParams { cmd: named, msg }) = &r else { panic!("{cmd} {given}: {r:?}") };
assert_eq!((named.as_str(), msg), (*cmd, &want), "{cmd} {given}");
assert!(s.doc().unwrap().doc == before, "{cmd} {given}: the document changed");
assert_eq!(s.doc().unwrap().selection.objects, vec![NodeId(ids[3])], "{cmd} {given}: the selection stays");
}
}
}
#[test]
fn a_command_that_fails_after_selecting_its_ids_puts_the_selection_back() {
let (mut s, ids) = doc();
+2
View File
@@ -4770,6 +4770,8 @@ imageTrace Outline Obrys
@msg {key} must be an array of non-negative integer object ids {key} musí být pole ID objektů, která jsou nezáporná celá čísla
@msg invalid object id {value}: expected a non-negative integer neplatné ID objektu {value}: očekává se nezáporné celé číslo
@msg no such object id {value} objekt s ID {value} neexistuje
@msg id {value} is a layer, not an object ID {value} je vrstva, nikoli objekt
@msg id {value} is a layer, not an object; move layers with layer.move ID {value} je vrstva, nikoli objekt; vrstvy přesunete pomocí layer.move
@msg automation filesystem access is not granted: read authority is absent: {path} přístup automatizace k systému souborů není udělen: chybí oprávnění ke čtení: {path}
@msg automation filesystem access is not granted: write authority is absent: {path} přístup automatizace k systému souborů není udělen: chybí oprávnění k zápisu: {path}
@msg automation path rejected: outside the read root {root}: {path} cesta automatizace odmítnuta: mimo kořen pro čtení {root}: {path}
Can't render this file because it contains an unexpected character in line 2 and column 73.
+2
View File
@@ -4429,6 +4429,8 @@ theme Appearance Erscheinungsbild
@msg {key} must be an array of non-negative integer object ids {key} muss ein Array von Objekt-IDs sein, die nicht negative ganze Zahlen sind
@msg invalid object id {value}: expected a non-negative integer ungültige Objekt-ID {value}: erwartet wird eine nicht negative ganze Zahl
@msg no such object id {value} kein Objekt mit der ID {value}
@msg id {value} is a layer, not an object die ID {value} ist eine Ebene, kein Objekt
@msg id {value} is a layer, not an object; move layers with layer.move die ID {value} ist eine Ebene, kein Objekt; verschieben Sie Ebenen mit layer.move
@msg automation filesystem access is not granted: read authority is absent: {path} Dateisystemzugriff für die Automatisierung ist nicht gewährt: Die Leseberechtigung fehlt: {path}
@msg automation filesystem access is not granted: write authority is absent: {path} Dateisystemzugriff für die Automatisierung ist nicht gewährt: Die Schreibberechtigung fehlt: {path}
@msg automation path rejected: outside the read root {root}: {path} Automatisierungspfad abgelehnt: außerhalb des Lesestammordners {root}: {path}
Can't render this file because it contains an unexpected character in line 2 and column 73.
+2
View File
@@ -4470,6 +4470,8 @@ theme Appearance Εμφάνιση
@msg {key} must be an array of non-negative integer object ids {key}: πρέπει να είναι πίνακας αναγνωριστικών αντικειμένων που είναι μη αρνητικοί ακέραιοι
@msg invalid object id {value}: expected a non-negative integer μη έγκυρο αναγνωριστικό αντικειμένου {value}: αναμένεται μη αρνητικός ακέραιος
@msg no such object id {value} δεν υπάρχει αντικείμενο με αναγνωριστικό {value}
@msg id {value} is a layer, not an object το αναγνωριστικό {value} είναι επίπεδο, όχι αντικείμενο
@msg id {value} is a layer, not an object; move layers with layer.move το αναγνωριστικό {value} είναι επίπεδο, όχι αντικείμενο· μετακινήστε τα επίπεδα με το layer.move
@msg automation filesystem access is not granted: read authority is absent: {path} δεν έχει επιτραπεί πρόσβαση αυτοματισμού στο σύστημα αρχείων: δεν υπάρχει δικαίωμα ανάγνωσης: {path}
@msg automation filesystem access is not granted: write authority is absent: {path} δεν έχει επιτραπεί πρόσβαση αυτοματισμού στο σύστημα αρχείων: δεν υπάρχει δικαίωμα εγγραφής: {path}
@msg automation path rejected: outside the read root {root}: {path} απορρίφθηκε η διαδρομή αυτοματισμού: εκτός ρίζας ανάγνωσης {root}: {path}
Can't render this file because it contains an unexpected character in line 2066 and column 19.
+2
View File
@@ -4491,6 +4491,8 @@ axis Both Ambos
@msg {key} must be an array of non-negative integer object ids {key} debe ser una lista de identificadores de objeto que sean enteros no negativos
@msg invalid object id {value}: expected a non-negative integer identificador de objeto no válido {value}: se esperaba un entero no negativo
@msg no such object id {value} no existe el objeto con el identificador {value}
@msg id {value} is a layer, not an object el identificador {value} es una capa, no un objeto
@msg id {value} is a layer, not an object; move layers with layer.move el identificador {value} es una capa, no un objeto; mueva las capas con layer.move
@msg automation filesystem access is not granted: read authority is absent: {path} la automatización no tiene acceso al sistema de archivos: falta el permiso de lectura: {path}
@msg automation filesystem access is not granted: write authority is absent: {path} la automatización no tiene acceso al sistema de archivos: falta el permiso de escritura: {path}
@msg automation path rejected: outside the read root {root}: {path} ruta de automatización rechazada: fuera de la carpeta raíz de lectura {root}: {path}
Can't render this file because it contains an unexpected character in line 2 and column 73.
+2
View File
@@ -4677,6 +4677,8 @@ imageTrace Outline Ääriviiva
@msg {key} must be an array of non-negative integer object ids {key} on oltava taulukko objektitunnuksia, jotka ovat ei-negatiivisia kokonaislukuja
@msg invalid object id {value}: expected a non-negative integer virheellinen objektitunnus {value}: odotettiin ei-negatiivista kokonaislukua
@msg no such object id {value} objektia tunnuksella {value} ei ole
@msg id {value} is a layer, not an object tunnus {value} on taso, ei objekti
@msg id {value} is a layer, not an object; move layers with layer.move tunnus {value} on taso, ei objekti; siirrä tasoja komennolla layer.move
@msg automation filesystem access is not granted: read authority is absent: {path} automaation tiedostojärjestelmäkäyttöä ei ole myönnetty: lukuoikeus puuttuu: {path}
@msg automation filesystem access is not granted: write authority is absent: {path} automaation tiedostojärjestelmäkäyttöä ei ole myönnetty: kirjoitusoikeus puuttuu: {path}
@msg automation path rejected: outside the read root {root}: {path} automaation polku hylättiin: lukujuuren {root} ulkopuolella: {path}
Can't render this file because it contains an unexpected character in line 2 and column 73.
+2
View File
@@ -4502,6 +4502,8 @@ axis Both Les deux
@msg {key} must be an array of non-negative integer object ids {key} doit être un tableau d’identifiants d’objet, entiers positifs ou nuls
@msg invalid object id {value}: expected a non-negative integer identifiant d’objet {value} non valide (un entier positif ou nul est attendu)
@msg no such object id {value} aucun objet ne porte l’identifiant {value}
@msg id {value} is a layer, not an object l’identifiant {value} désigne un calque, pas un objet
@msg id {value} is a layer, not an object; move layers with layer.move l’identifiant {value} désigne un calque, pas un objet ; déplacez les calques avec layer.move
@msg automation filesystem access is not granted: read authority is absent: {path} l’automatisation n’a pas accès au système de fichiers : aucune autorisation de lecture : {path}
@msg automation filesystem access is not granted: write authority is absent: {path} l’automatisation n’a pas accès au système de fichiers : aucune autorisation d’écriture : {path}
@msg automation path rejected: outside the read root {root}: {path} chemin d’automatisation refusé : hors du dossier racine de lecture {root} : {path}
Can't render this file because it contains an unexpected character in line 2 and column 73.
+2
View File
@@ -4849,6 +4849,8 @@ imageTrace Outline Körvonal
@msg {key} must be an array of non-negative integer object ids {key}: objektumazonosítók tömbje kell, mindegyik nemnegatív egész szám
@msg invalid object id {value}: expected a non-negative integer érvénytelen objektumazonosító: {value} (nemnegatív egész szám kell)
@msg no such object id {value} nincs ilyen objektumazonosító: {value}
@msg id {value} is a layer, not an object a(z) {value} azonosító egy réteg, nem objektum
@msg id {value} is a layer, not an object; move layers with layer.move a(z) {value} azonosító egy réteg, nem objektum; a rétegeket a layer.move paranccsal helyezheti át
@msg object {0} cannot have children ennek az objektumnak nem lehetnek gyermekei: {0}
@msg object {id} is not a path az objektum nem útvonal: {id}
@msg object {id} is not a selected top-level object az objektum nem kijelölt legfelső szintű objektum: {id}
Can't render this file because it contains an unexpected character in line 2 and column 73.
+2
View File
@@ -4531,6 +4531,8 @@ axis Both Entrambi
@msg {key} must be an array of non-negative integer object ids {key} deve essere un array di ID oggetto interi non negativi
@msg invalid object id {value}: expected a non-negative integer ID oggetto {value} non valido: è richiesto un intero non negativo
@msg no such object id {value} nessun oggetto con ID {value}
@msg id {value} is a layer, not an object l’ID {value} è un livello, non un oggetto
@msg id {value} is a layer, not an object; move layers with layer.move l’ID {value} è un livello, non un oggetto; sposta i livelli con layer.move
@msg automation filesystem access is not granted: read authority is absent: {path} l'automazione non ha accesso al file system: manca l'autorizzazione di lettura: {path}
@msg automation filesystem access is not granted: write authority is absent: {path} l'automazione non ha accesso al file system: manca l'autorizzazione di scrittura: {path}
@msg automation path rejected: outside the read root {root}: {path} percorso di automazione rifiutato: fuori dalla cartella radice di lettura {root}: {path}
Can't render this file because it contains an unexpected character in line 2 and column 73.
+2
View File
@@ -4569,6 +4569,8 @@ swatch Bright Violet ビビッドバイオレット
@msg {key} must be an array of non-negative integer object ids {key} にはオブジェクト ID (0 以上の整数) の配列を指定してください
@msg invalid object id {value}: expected a non-negative integer オブジェクト ID {value} は正しくありません: 0 以上の整数を指定してください
@msg no such object id {value} ID が {value} のオブジェクトは見つかりません
@msg id {value} is a layer, not an object ID {value} はオブジェクトではなくレイヤーです
@msg id {value} is a layer, not an object; move layers with layer.move ID {value} はオブジェクトではなくレイヤーです。レイヤーは layer.move で移動してください
@msg automation filesystem access is not granted: read authority is absent: {path} 自動化にはファイルシステムへのアクセスが許可されていません: 読み込み権限がありません: {path}
@msg automation filesystem access is not granted: write authority is absent: {path} 自動化にはファイルシステムへのアクセスが許可されていません: 書き込み権限がありません: {path}
@msg automation path rejected: outside the read root {root}: {path} 自動化のパスを拒否しました: 読み込みルート {root} の外です: {path}
Can't render this file because it contains an unexpected character in line 2 and column 73.
+2
View File
@@ -4218,6 +4218,8 @@ font-technology Variable ცვლადი
@msg {key} must be an array of non-negative integer object ids {key} უნდა იყოს ობიექტების id-ების მასივი, სადაც ყოველი id არაუარყოფითი მთელი რიცხვია
@msg invalid object id {value}: expected a non-negative integer ობიექტის არასწორი id {value}: მოსალოდნელია არაუარყოფითი მთელი რიცხვი
@msg no such object id {value} ობიექტი id-ით {value} არ არსებობს
@msg id {value} is a layer, not an object id {value} შრეა და არა ობიექტი
@msg id {value} is a layer, not an object; move layers with layer.move id {value} შრეა და არა ობიექტი; შრეების გადასატანად გამოიყენეთ layer.move
@msg automation filesystem access is not granted: read authority is absent: {path} ავტომატიზაციას ფაილურ სისტემაზე წვდომა არ აქვს: წაკითხვის უფლება არ არის: {path}
@msg automation filesystem access is not granted: write authority is absent: {path} ავტომატიზაციას ფაილურ სისტემაზე წვდომა არ აქვს: ჩაწერის უფლება არ არის: {path}
@msg automation path rejected: outside the read root {root}: {path} ავტომატიზაციის გზა უარყოფილია: წაკითხვის ძირის {root} გარეთაა: {path}
Can't render this file because it contains an unexpected character in line 2 and column 73.
+2
View File
@@ -4501,6 +4501,8 @@ theme Appearance 외관
@msg {key} must be an array of non-negative integer object ids {key}은(는) 음이 아닌 정수인 개체 id의 배열이어야 합니다
@msg invalid object id {value}: expected a non-negative integer 개체 id {value}이(가) 올바르지 않습니다: 음이 아닌 정수여야 합니다
@msg no such object id {value} id가 {value}인 개체가 없습니다
@msg id {value} is a layer, not an object id {value}은(는) 개체가 아닌 레이어입니다
@msg id {value} is a layer, not an object; move layers with layer.move id {value}은(는) 개체가 아닌 레이어입니다. 레이어는 layer.move로 이동하세요
@msg automation filesystem access is not granted: read authority is absent: {path} 자동화 파일 시스템 접근이 허용되지 않았습니다: 읽기 권한이 없습니다: {path}
@msg automation filesystem access is not granted: write authority is absent: {path} 자동화 파일 시스템 접근이 허용되지 않았습니다: 쓰기 권한이 없습니다: {path}
@msg automation path rejected: outside the read root {root}: {path} 자동화 경로가 거부되었습니다: 읽기 루트 {root} 밖입니다: {path}
Can't render this file because it contains an unexpected character in line 2 and column 73.
+2
View File
@@ -4595,6 +4595,8 @@ imageTrace Outline Kontur
@msg {key} must be an array of non-negative integer object ids {key} musi być tablicą identyfikatorów obiektów, które są nieujemnymi liczbami całkowitymi
@msg invalid object id {value}: expected a non-negative integer nieprawidłowy identyfikator obiektu {value}: oczekiwano nieujemnej liczby całkowitej
@msg no such object id {value} brak obiektu o identyfikatorze {value}
@msg id {value} is a layer, not an object identyfikator {value} oznacza warstwę, a nie obiekt
@msg id {value} is a layer, not an object; move layers with layer.move identyfikator {value} oznacza warstwę, a nie obiekt; warstwy przenosi się za pomocą layer.move
@msg automation filesystem access is not granted: read authority is absent: {path} nie przyznano dostępu automatyzacji do systemu plików: brak uprawnień do odczytu: {path}
@msg automation filesystem access is not granted: write authority is absent: {path} nie przyznano dostępu automatyzacji do systemu plików: brak uprawnień do zapisu: {path}
@msg automation path rejected: outside the read root {root}: {path} odrzucono ścieżkę automatyzacji: poza katalogiem głównym odczytu {root}: {path}
Can't render this file because it contains an unexpected character in line 2 and column 73.
+2
View File
@@ -4036,6 +4036,8 @@ axis Both Ambos
@msg {key} must be an array of non-negative integer object ids {key} deve ser uma matriz de ids de objeto que sejam inteiros não negativos
@msg invalid object id {value}: expected a non-negative integer id de objeto inválido {value}: era esperado um inteiro não negativo
@msg no such object id {value} não existe objeto com o id {value}
@msg id {value} is a layer, not an object o id {value} é uma camada, não um objeto
@msg id {value} is a layer, not an object; move layers with layer.move o id {value} é uma camada, não um objeto; mova camadas com layer.move
@msg automation filesystem access is not granted: read authority is absent: {path} o acesso da automação ao sistema de arquivos não foi concedido: falta autorização de leitura: {path}
@msg automation filesystem access is not granted: write authority is absent: {path} o acesso da automação ao sistema de arquivos não foi concedido: falta autorização de gravação: {path}
@msg automation path rejected: outside the read root {root}: {path} caminho da automação rejeitado: fora da raiz de leitura {root}: {path}
Can't render this file because it contains an unexpected character in line 6 and column 47.
+2
View File
@@ -4529,6 +4529,8 @@ axis Both Оба
@msg {key} must be an array of non-negative integer object ids {key} должно быть массивом идентификаторов объектов, которые являются неотрицательными целыми числами
@msg invalid object id {value}: expected a non-negative integer недопустимый идентификатор объекта {value}: ожидается неотрицательное целое число
@msg no such object id {value} объект с идентификатором {value} не существует
@msg id {value} is a layer, not an object идентификатор {value} относится к слою, а не к объекту
@msg id {value} is a layer, not an object; move layers with layer.move идентификатор {value} относится к слою, а не к объекту; перемещайте слои с помощью layer.move
@msg automation filesystem access is not granted: read authority is absent: {path} у автоматизации нет доступа к файловой системе: нет права на чтение: {path}
@msg automation filesystem access is not granted: write authority is absent: {path} у автоматизации нет доступа к файловой системе: нет права на запись: {path}
@msg automation path rejected: outside the read root {root}: {path} путь автоматизации отклонён: вне корневой папки для чтения {root}: {path}
Can't render this file because it contains an unexpected character in line 2 and column 73.
+2
View File
@@ -4412,6 +4412,8 @@ axis Both Båda
@msg {key} must be an array of non-negative integer object ids {key} måste vara en array med objekt-id:n som är icke-negativa heltal
@msg invalid object id {value}: expected a non-negative integer ogiltigt objekt-id {value}: ett icke-negativt heltal förväntades
@msg no such object id {value} det finns inget objekt med id {value}
@msg id {value} is a layer, not an object id {value} är ett lager, inte ett objekt
@msg id {value} is a layer, not an object; move layers with layer.move id {value} är ett lager, inte ett objekt; flytta lager med layer.move
@msg automation filesystem access is not granted: read authority is absent: {path} automatiseringen har inte fått åtkomst till filsystemet: läsbehörighet saknas: {path}
@msg automation filesystem access is not granted: write authority is absent: {path} automatiseringen har inte fått åtkomst till filsystemet: skrivbehörighet saknas: {path}
@msg automation path rejected: outside the read root {root}: {path} automatiseringssökvägen avvisades: utanför läsroten {root}: {path}
Can't render this file because it contains an unexpected character in line 5 and column 25.
+2
View File
@@ -5201,6 +5201,8 @@ theme Appearance Görünüm
@msg {key} must be an array of non-negative integer object ids {key}, negatif olmayan tam sayı nesne kimlikleri dizisi olmalıdır
@msg invalid object id {value}: expected a non-negative integer geçersiz nesne kimliği {value}: negatif olmayan bir tam sayı bekleniyordu
@msg no such object id {value} böyle bir nesne kimliği yok: {value}
@msg id {value} is a layer, not an object {value} kimliği bir katmana ait, bir nesneye değil
@msg id {value} is a layer, not an object; move layers with layer.move {value} kimliği bir katmana ait, bir nesneye değil; katmanları layer.move ile taşıyın
@msg {key} must be Unix seconds (an integer) or null {key}, Unix saniyesi (bir tam sayı) veya null olmalıdır
@msg its zlib compression is damaged zlib sıkıştırması hasarlı
@msg its Zstandard compression is damaged Zstandard sıkıştırması hasarlı
Can't render this file because it contains an unexpected character in line 5 and column 25.
+2
View File
@@ -4515,6 +4515,8 @@ axis Both Обидві
@msg {key} must be an array of non-negative integer object ids {key} має бути масивом ідентифікаторів об’єктів, які є невід’ємними цілими числами
@msg invalid object id {value}: expected a non-negative integer неприпустимий ідентифікатор об’єкта {value}: очікується невід’ємне ціле число
@msg no such object id {value} об’єкт з ідентифікатором {value} не існує
@msg id {value} is a layer, not an object ідентифікатор {value} належить шару, а не об’єкту
@msg id {value} is a layer, not an object; move layers with layer.move ідентифікатор {value} належить шару, а не об’єкту; переміщуйте шари за допомогою layer.move
@msg automation filesystem access is not granted: read authority is absent: {path} автоматизація не має доступу до файлової системи: немає права на читання: {path}
@msg automation filesystem access is not granted: write authority is absent: {path} автоматизація не має доступу до файлової системи: немає права на запис: {path}
@msg automation path rejected: outside the read root {root}: {path} шлях автоматизації відхилено: поза кореневою папкою для читання {root}: {path}
Can't render this file because it contains an unexpected character in line 747 and column 40.
+2
View File
@@ -4498,6 +4498,8 @@ theme Appearance Giao diện
@msg {key} must be an array of non-negative integer object ids {key} phải là một mảng id đối tượng là số nguyên không âm
@msg invalid object id {value}: expected a non-negative integer id đối tượng {value} không hợp lệ: cần một số nguyên không âm
@msg no such object id {value} không có đối tượng nào có id {value}
@msg id {value} is a layer, not an object id {value} là một lớp, không phải đối tượng
@msg id {value} is a layer, not an object; move layers with layer.move id {value} là một lớp, không phải đối tượng; hãy di chuyển lớp bằng layer.move
@msg object {0} cannot have children đối tượng {0} không thể có phần tử con
@msg object {id} is not a path đối tượng {id} không phải là đường dẫn
@msg object {id} is not a selected top-level object đối tượng {id} không phải là đối tượng cấp cao nhất đã chọn
Can't render this file because it contains an unexpected character in line 4051 and column 10.
+2
View File
@@ -4288,6 +4288,8 @@ imageTrace Outline 轮廓
@msg {key} must be an array of non-negative integer object ids {key} 必须是由非负整数对象 id 组成的数组
@msg invalid object id {value}: expected a non-negative integer 无效的对象 id {value}:应为非负整数
@msg no such object id {value} 没有 id 为 {value} 的对象
@msg id {value} is a layer, not an object id {value} 是图层,不是对象
@msg id {value} is a layer, not an object; move layers with layer.move id {value} 是图层,不是对象;请使用 layer.move 移动图层
@msg automation filesystem access is not granted: read authority is absent: {path} 未授予自动化文件系统访问权限:缺少读取权限:{path}
@msg automation filesystem access is not granted: write authority is absent: {path} 未授予自动化文件系统访问权限:缺少写入权限:{path}
@msg automation path rejected: outside the read root {root}: {path} 已拒绝自动化路径:位于读取根目录 {root} 之外:{path}
Can't render this file because it contains an unexpected character in line 2 and column 73.
+2
View File
@@ -5052,6 +5052,8 @@ lighting Light 光源
@msg {key} must be an array of non-negative integer object ids {key} 必須是由非負整數物件 id 組成的陣列
@msg invalid object id {value}: expected a non-negative integer 無效的物件 id {value}:應為非負整數
@msg no such object id {value} 沒有 id 為 {value} 的物件
@msg id {value} is a layer, not an object id {value} 是圖層,不是物件
@msg id {value} is a layer, not an object; move layers with layer.move id {value} 是圖層,不是物件;請使用 layer.move 移動圖層
Move Anchor Point 移動錨點
@msg {label} keeps 1 of the document's {n} artboards: the file reopens with one. Turn on Preserve Editing Capabilities to keep them all. {label} 只保留文件 {n} 個工作區域中的 1 個:檔案重新開啟時只有一個。開啟「保留編輯功能」可全部保留。
Chalk & Charcoal… 粉筆和炭筆…
Can't render this file because it contains an unexpected character in line 6 and column 47.
+5
View File
@@ -347,6 +347,11 @@ currently describes them in prose, so MCP does not guess schemas or silently rem
Coordinates are points in document space: y points down, the origin is the first artboard's top-left, and a new
document is 612 × 792 (US Letter). New objects become the selection. Most commands act on the selection or on
explicit `ids`. A command that leaves out an object selected inside a selected group also leaves it out when `ids`
list it together with a group that holds it. The commands that select their `ids` first (`object.group`, the
`object.arrange.*` commands, `object.move`, the Pathfinder commands and the others like them) refuse an id that names a
layer or sublayer, names no object or is not a non-negative integer, with an error that names the command that was run,
and leave the document and the selection unchanged; `layer.move` reorders layers.
explicit `ids`, which stand in for the selection, so they work with nothing selected. Where a command's params say
`ids?|id?` (or `id?, ids?: … (instead of id)`), `id` is `ids` of one object: `{"id": 7}` does what `{"ids": [7]}`
does, with or without a selection, and an `id` or `ids` that is malformed (not a non-negative integer) or names no