Merge pull request #5118 from dotCooCoo/fix/vars-p1

Variables: art on a locked artboard is not bound or rewritten by a data set
This commit is contained in:
BFlat
2026-11-02 16:04:49 +07:00
committed by GitHub
25 changed files with 158 additions and 30 deletions
+42 -15
View File
@@ -6,7 +6,7 @@ use std::collections::{BTreeMap, BTreeSet};
use serde::{Deserialize, Serialize};
use super::{Document, NodeId, NodeKind, TextKind};
use super::{Document, LockedArtboards, NodeId, NodeKind, TextKind};
/// What a variable drives.
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
@@ -190,17 +190,32 @@ impl Document {
}
/// Whether a variable may be bound to the object `id`: it is in the document, neither it nor
/// anything above it is locked, and nothing above it is hidden. Its own visibility doesn't
/// count, as that is what a visibility variable drives.
/// anything above it is locked, nothing above it is hidden, and it is not on a locked artboard
/// ([`Document::on_locked_artboard`]). Its own visibility doesn't count, as that is what a
/// visibility variable drives.
pub fn variable_target(&self, id: NodeId) -> bool {
self.ancestry(id).is_some_and(|a| a.iter().all(|i| self.node(*i).is_some_and(|n| !n.locked && (n.visible || *i == id))))
self.variable_target_with(&self.locked_artboards(), id)
}
/// Whether a data set reads and rewrites the bound object `id`: it is in the document and
/// neither it nor anything above it is locked. Hidden objects count, and so do objects in a
/// hidden layer or group.
/// [`Document::variable_target`] with the locked artboards `locks` of this document, measured
/// once for many ids.
pub fn variable_target_with(&self, locks: &LockedArtboards, id: NodeId) -> bool {
self.ancestry(id).is_some_and(|a| a.iter().all(|i| self.node(*i).is_some_and(|n| !n.locked && (n.visible || *i == id))))
&& !locks.holds_id(id)
}
/// Whether a data set reads and rewrites the bound object `id`: it is in the document, neither
/// it nor anything above it is locked, and it is not on a locked artboard
/// ([`Document::on_locked_artboard`]). Hidden objects count, and so do objects in a hidden
/// layer or group.
pub fn dataset_target(&self, id: NodeId) -> bool {
self.ancestry(id).is_some_and(|a| a.iter().all(|i| self.node(*i).is_some_and(|n| !n.locked)))
self.dataset_target_with(&self.locked_artboards(), id)
}
/// [`Document::dataset_target`] with the locked artboards `locks` of this document, measured
/// once for many ids.
pub fn dataset_target_with(&self, locks: &LockedArtboards, id: NodeId) -> bool {
self.ancestry(id).is_some_and(|a| a.iter().all(|i| self.node(*i).is_some_and(|n| !n.locked))) && !locks.holds_id(id)
}
/// The type objects of the story that the type object `id` belongs to, in thread order: the
@@ -228,21 +243,32 @@ impl Document {
/// Whether a data set reads and rewrites the text of the type object `id`: every frame of its
/// story ([`Document::story_of`]) is a [`Document::dataset_target`].
pub fn story_target(&self, id: NodeId) -> bool {
self.story_of(id).into_iter().all(|f| self.dataset_target(f))
self.story_target_with(&self.locked_artboards(), id)
}
/// [`Document::story_target`] with the locked artboards `locks` of this document, measured
/// once for many ids.
pub fn story_target_with(&self, locks: &LockedArtboards, id: NodeId) -> bool {
self.story_of(id).into_iter().all(|f| self.dataset_target_with(locks, f))
}
/// What the object `id` holds for the variable of `kind`: its characters (the whole story
/// for a frame of threaded text), whether it shows, or a linked image's path. `None` when the
/// object is gone, is not of that kind, has no link path yet (an embedded image), or is locked
/// or in a locked layer or group, or for text when a frame of its story is (the document's
/// value is whatever it was left at).
/// object is gone, is not of that kind, has no link path yet (an embedded image), or is locked,
/// in a locked layer or group, or on a locked artboard, or for text when a frame of its story
/// is (the document's value is whatever it was left at).
pub fn variable_value(&self, id: NodeId, kind: VariableKind) -> Option<DataValue> {
if !self.dataset_target(id) {
self.variable_value_with(&self.locked_artboards(), id, kind)
}
/// [`Document::variable_value`] with the locked artboards `locks` of this document.
fn variable_value_with(&self, locks: &LockedArtboards, id: NodeId, kind: VariableKind) -> Option<DataValue> {
if !self.dataset_target_with(locks, id) {
return None;
}
let node = self.node(id)?;
match (kind, &node.kind) {
(VariableKind::Text, NodeKind::Text(_)) if self.story_target(id) => Some(DataValue::Text(self.story_text(id))),
(VariableKind::Text, NodeKind::Text(_)) if self.story_target_with(locks, id) => Some(DataValue::Text(self.story_text(id))),
(VariableKind::Visibility, _) => Some(DataValue::Visible(node.visible)),
(VariableKind::Image, NodeKind::Image(im)) => im.link.as_ref().map(|l| DataValue::Image(l.path.clone())),
(VariableKind::Graph, _) => node.extras().graph.as_ref().map(|g| DataValue::Graph(g.to_csv())),
@@ -257,10 +283,11 @@ impl Document {
/// still matches what it says.
pub fn captured_values(&self) -> BTreeMap<String, DataValue> {
let mut out = BTreeMap::new();
let locks = self.locked_artboards();
for v in &self.variables.variables {
// An object driven by several variables of the same kind reads from the first one
// bound, so a capture is one value per variable and applies back the same way.
let value = self.variables.objects_of(&v.name).into_iter().find_map(|id| self.variable_value(id, v.kind));
let value = self.variables.objects_of(&v.name).into_iter().find_map(|id| self.variable_value_with(&locks, id, v.kind));
if let Some(value) = value {
out.insert(v.name.clone(), value);
}
+31 -13
View File
@@ -138,13 +138,15 @@ fn names_param(p: &Value, cmd: &str, fallback: Option<String>, nothing: &str) ->
}
}
/// Refuse what a variable of `kind` can't be bound to: art that is locked or on a hidden or locked
/// layer; a text variable only drives type; an image variable only drives an image object.
/// Refuse what a variable of `kind` can't be bound to: art that is locked, on a hidden or locked
/// layer, or on a locked artboard; a text variable only drives type; an image variable only drives
/// an image object.
fn check_bindable(doc: &vectorcraft_doc::Document, ids: &[NodeId], kind: VariableKind, cmd: &str) -> Result<()> {
let locks = doc.locked_artboards();
for id in ids {
match doc.node(*id) {
None => return Err(EngineError::NoNode(*id)),
Some(_) if !doc.variable_target(*id) => return Err(bad(cmd, not_a_target(doc, *id))),
Some(_) if !doc.variable_target_with(&locks, *id) => return Err(bad(cmd, not_a_target(doc, *id))),
Some(n) if kind == VariableKind::Text && !matches!(n.kind, NodeKind::Text(_)) => {
return Err(bad(cmd, format!("node {} is not type", id.0)));
}
@@ -161,7 +163,7 @@ fn check_bindable(doc: &vectorcraft_doc::Document, ids: &[NodeId], kind: Variabl
}
/// Why `variable_target` refuses `id`: the object is locked, a group or layer that holds it is
/// locked, or one that holds it is hidden, checked in that order.
/// locked, one that holds it is hidden, or it is on a locked artboard, checked in that order.
fn not_a_target(doc: &vectorcraft_doc::Document, id: NodeId) -> String {
let holders: Vec<&vectorcraft_doc::Node> =
doc.ancestry(id).unwrap_or_default().into_iter().filter(|i| *i != id).filter_map(|i| doc.node(i)).collect();
@@ -169,8 +171,10 @@ fn not_a_target(doc: &vectorcraft_doc::Document, id: NodeId) -> String {
format!("node {} is locked", id.0)
} else if holders.iter().any(|n| n.locked) {
format!("node {} is in a locked group or layer", id.0)
} else {
} else if holders.iter().any(|n| !n.visible) {
format!("node {} is in a hidden group or layer", id.0)
} else {
format!("node {} is on a locked artboard", id.0)
}
}
@@ -483,7 +487,7 @@ fn dataset_capture(s: &mut Session, p: &Value) -> Result<Value> {
/// Update Data Set: write what the bound objects hold now into the row that is active, for each
/// variable the row holds. A variable whose objects report no value (locked, inside a locked
/// layer or group, or gone) keeps the row's value. With `all`, every other variable the
/// layer or group, on a locked artboard, or gone) keeps the row's value. With `all`, every other variable the
/// objects report a value for is added to the row. Without an active row there is nothing to
/// update, so say so rather than picking one. With every bound object locked, no value is
/// written; an update that writes no value adds no undo step.
@@ -557,6 +561,20 @@ fn apply_dataset(s: &mut Session, name: &str) -> Result<Value> {
for v in &d.variables.variables {
pairs.extend(d.variables.objects_of(&v.name).into_iter().map(|id| (id, v.name.clone())));
}
// Which bound objects the row may rewrite, measured once before any of them changes, so
// text that grows onto a locked artboard part way through is still rewritten. Each id is
// keyed by whether a text value is meant for it, which checks every frame of its story.
let targets: BTreeSet<(NodeId, bool)> = {
let locks = d.locked_artboards();
let mut out = BTreeSet::new();
for (id, var) in &pairs {
let text = d.variables.variable(var).is_some_and(|v| v.kind == VariableKind::Text);
if if text { d.story_target_with(&locks, *id) } else { d.dataset_target_with(&locks, *id) } {
out.insert((*id, text));
}
}
out
};
// Whether an object is bound to a variable that this row has a value for (the reply's `warning`).
let bound = pairs.iter().any(|(_, var)| ds.values.contains_key(var));
let mut applied = 0usize;
@@ -574,12 +592,12 @@ fn apply_dataset(s: &mut Session, name: &str) -> Result<Value> {
continue;
}
};
// Locked art, art in a locked layer or group, and text whose object is gone, can't be
// rewritten: skipped and counted, like the rest. Hidden art is rewritten, in a hidden
// layer or group too, and stays hidden unless a visibility value shows it. A text value
// rewrites the whole story of threaded text, so it skips when any frame of it is locked.
let target = if kind == VariableKind::Text { d.story_target(id) } else { d.dataset_target(id) };
if !target {
// Locked art, art in a locked layer or group or on a locked artboard, and text whose
// object is gone, can't be rewritten: skipped and counted, like the rest. Hidden art
// is rewritten, in a hidden layer or group too, and stays hidden unless a visibility
// value shows it. A text value rewrites the whole story of threaded text, so it skips
// when any frame of it is locked or on a locked artboard.
if !targets.contains(&(id, kind == VariableKind::Text)) {
skipped += 1;
continue;
}
@@ -772,7 +790,7 @@ pub fn specs() -> Vec<CommandSpec> {
"Update Data Set",
["Window", "Variables"],
None,
"{all?: bool} write what the bound objects hold now into the active dataset, for each variable the dataset holds; a variable whose objects report no value (locked, inside a locked layer or group, or gone) keeps the dataset's value. `all: true` also adds every other variable the objects report a value for; `left` names the variables it didn't write → {values, left}",
"{all?: bool} write what the bound objects hold now into the active dataset, for each variable the dataset holds; a variable whose objects report no value (locked, inside a locked layer or group, on a locked artboard, or gone) keeps the dataset's value. `all: true` also adds every other variable the objects report a value for; `left` names the variables it didn't write → {values, left}",
has_doc,
dataset_update
),
+62
View File
@@ -438,6 +438,68 @@ fn locked_art_is_neither_bound_nor_rewritten() {
assert!(!s.doc().unwrap().doc.node(r).unwrap().visible, "the unlocked rectangle still applied");
}
/// The art on a locked artboard acts as locked art: a data set skips it, Update Data Set reads
/// nothing from it, and it takes no new binding. Unlocking the artboard lets the data set rewrite it.
#[test]
fn art_on_a_locked_artboard_is_neither_bound_nor_rewritten() {
let mut s = session();
let t = NodeId(s.execute("text.create", &json!({"x": 2050, "y": 50, "text": "cat"})).unwrap()["id"].as_u64().unwrap());
let fresh = NodeId(s.execute("text.create", &json!({"x": 2100, "y": 100, "text": "new"})).unwrap()["id"].as_u64().unwrap());
let r = rect(&mut s);
s.execute("artboard.new", &json!({"x": 2000, "y": 0, "width": 400, "height": 400})).unwrap();
s.execute("variable.define", &json!({"name": "Name", "kind": "text"})).unwrap();
s.execute("variable.define", &json!({"name": "Show", "kind": "visibility"})).unwrap();
s.execute("variable.define", &json!({"name": "Box", "kind": "visibility"})).unwrap();
s.execute("variable.bind", &json!({"variable": "Name", "ids": [t.0]})).unwrap();
s.execute("variable.bind", &json!({"variable": "Show", "ids": [t.0]})).unwrap();
s.execute("variable.bind", &json!({"variable": "Box", "ids": [r.0]})).unwrap();
s.execute("dataset.capture", &json!({"name": "A"})).unwrap();
s.execute("dataset.new", &json!({"name": "B", "values": {"Name": "Bob", "Show": false, "Box": false}})).unwrap();
s.execute("select.none", &json!({})).unwrap();
s.execute("artboard.setProps", &json!({"index": 1, "locked": true})).unwrap();
let e = s.execute("variable.bind", &json!({"variable": "Name", "ids": [fresh.0]})).unwrap_err().to_string();
assert!(e.contains(&format!("node {} is on a locked artboard", fresh.0)), "{e}");
let v = s.execute("dataset.select", &json!({"name": "B"})).unwrap();
assert_eq!((v["applied"].as_u64(), v["skipped"].as_u64()), (Some(1), Some(2)), "{v}");
assert_eq!(plain(&s, t), "cat", "the text on the locked artboard was left alone");
assert!(s.doc().unwrap().doc.node(t).unwrap().visible, "and still shows");
assert!(!s.doc().unwrap().doc.node(r).unwrap().visible, "the rectangle off it applied");
// Update Data Set keeps the row's values for the art it can't read.
let v = s.execute("dataset.update", &json!({})).unwrap();
assert_eq!(v["values"], 1, "{v}");
let row = s.doc().unwrap().doc.variables.dataset("B").unwrap().values.clone();
assert_eq!(row.get("Name"), Some(&vectorcraft_doc::DataValue::Text("Bob".into())));
assert_eq!(row.get("Show"), Some(&vectorcraft_doc::DataValue::Visible(false)));
s.execute("artboard.setProps", &json!({"index": 1, "locked": false})).unwrap();
let v = s.execute("dataset.select", &json!({"name": "B"})).unwrap();
assert_eq!((v["applied"].as_u64(), v["skipped"].as_u64()), (Some(3), Some(0)), "{v}");
assert_eq!(plain(&s, t), "Bob");
}
/// A locked artboard elsewhere in the document does not stop threaded type on an unlocked artboard
/// from having its whole story rewritten, and type on the locked artboard is still left alone.
#[test]
fn threaded_type_on_an_unlocked_artboard_is_rewritten_beside_a_locked_artboard() {
let (mut s, a, b, story) = threaded(200);
let far = NodeId(s.execute("text.create", &json!({"x": 2050, "y": 50, "text": "cat"})).unwrap()["id"].as_u64().unwrap());
s.execute("artboard.new", &json!({"x": 2000, "y": 0, "width": 400, "height": 400})).unwrap();
s.execute("variable.define", &json!({"name": "Name", "kind": "text"})).unwrap();
s.execute("variable.define", &json!({"name": "Tail", "kind": "text"})).unwrap();
s.execute("variable.bind", &json!({"variable": "Name", "ids": [a.0]})).unwrap();
s.execute("variable.bind", &json!({"variable": "Tail", "ids": [far.0]})).unwrap();
s.execute("dataset.new", &json!({"name": "B", "values": {"Name": "Bob", "Tail": "dog"}})).unwrap();
s.execute("select.none", &json!({})).unwrap();
s.execute("artboard.setProps", &json!({"index": 1, "locked": true})).unwrap();
let v = s.execute("dataset.select", &json!({"name": "B"})).unwrap();
assert_eq!((v["applied"].as_u64(), v["skipped"].as_u64()), (Some(1), Some(1)), "{v}");
assert_eq!((plain(&s, a), plain(&s, b)), ("Bob".to_string(), String::new()), "the whole story was rewritten");
assert_eq!(plain(&s, far), "cat", "the text on the locked artboard was left alone");
assert!(!story.is_empty());
}
/// Binding fails for locked art and for art in a hidden or locked group or layer, and the
/// error names which of the three applies.
#[test]
+1
View File
@@ -5275,6 +5275,7 @@ digits Malayalam Malaiàlam
@msg no user library folder here aquí no hi ha cap carpeta de biblioteca d’usuari
@msg no user workspace `{from}` no hi ha l’espai de treball d’usuari `{from}`
@msg node {_1} is not text el node {_1} no és text
@msg node {_1} is on a locked artboard el node {_1} és en un tauler bloquejat
@msg Non-finite dimension Cota no finita
@msg not a blend no és una fusió
@msg not a DXF drawing no és un dibuix DXF
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -4609,6 +4609,7 @@ imageTrace Outline Obrys
@msg no user library folder here zde není složka uživatelských knihoven
@msg no user workspace `{from}` uživatelský pracovní prostor `{from}` neexistuje
@msg node {_1} is not text uzel {_1} není text
@msg node {_1} is on a locked artboard uzel {_1} je na zamčené pracovní ploše
@msg not a DXF drawing nejde o výkres DXF
@msg not a VectorCraft file: {0} nejde o soubor VectorCraft: {0}
@msg not a VectorCraft shortcut set (missing `overrides`) nejde o sadu klávesových zkratek VectorCraft (chybí `overrides`)
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -4218,6 +4218,7 @@ theme Appearance Erscheinungsbild
@msg no user library folder here hier gibt es keinen Ordner für Benutzerbibliotheken
@msg no user workspace `{from}` kein Benutzerarbeitsbereich `{from}`
@msg node {_1} is not text Knoten {_1} ist kein Text
@msg node {_1} is on a locked artboard Knoten {_1} liegt auf einer gesperrten Zeichenfläche
@msg not a DXF drawing keine DXF-Zeichnung
@msg not a VectorCraft file: {0} keine VectorCraft-Datei: {0}
@msg not a VectorCraft shortcut set (missing `overrides`) kein VectorCraft-Tastaturbefehlssatz (`overrides` fehlt)
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -4257,6 +4257,7 @@ digits Malayalam Μαλαγιάλαμ
@msg no user library folder here δεν υπάρχει φάκελος βιβλιοθήκης χρήστη εδώ
@msg no user workspace `{from}` δεν υπάρχει χώρος εργασίας χρήστη `{from}`
@msg node {_1} is not text ο κόμβος {_1} δεν είναι κείμενο
@msg node {_1} is on a locked artboard ο κόμβος {_1} βρίσκεται σε κλειδωμένο πίνακα σχεδίασης
@msg not a DXF drawing δεν είναι σχέδιο DXF
@msg not a VectorCraft file: {0} δεν είναι αρχείο VectorCraft: {0}
@msg not a VectorCraft shortcut set (missing `overrides`) δεν είναι σύνολο συντομεύσεων VectorCraft (λείπει το `overrides`)
Can't render this file because it contains an unexpected character in line 163 and column 5.
+1
View File
@@ -4302,6 +4302,7 @@ axis Both Ambos
@msg no user library folder here aquí no hay ninguna carpeta de bibliotecas de usuario
@msg no user workspace `{from}` no existe el espacio de trabajo de usuario `{from}`
@msg node {_1} is not text el nodo {_1} no es texto
@msg node {_1} is on a locked artboard el nodo {_1} está en una mesa de trabajo bloqueada
@msg not a DXF drawing no es un dibujo DXF
@msg not a VectorCraft file: {0} no es un archivo de VectorCraft: {0}
@msg not a VectorCraft shortcut set (missing `overrides`) no es un conjunto de atajos de VectorCraft (falta `overrides`)
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -4517,6 +4517,7 @@ imageTrace Outline Ääriviiva
@msg no user library folder here täällä ei ole käyttäjäkirjastokansiota
@msg no user workspace `{from}` ei käyttäjän työtilaa `{from}`
@msg node {_1} is not text solmu {_1} ei ole tekstiä
@msg node {_1} is on a locked artboard solmu {_1} on lukitulla piirtoalustalla
@msg not a DXF drawing ei DXF-piirustus
@msg not a VectorCraft file: {0} ei VectorCraft-tiedosto: {0}
@msg not a VectorCraft shortcut set (missing `overrides`) ei VectorCraftin pikanäppäinjoukko (`overrides` puuttuu)
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -4292,6 +4292,7 @@ axis Both Les deux
@msg no user library folder here aucun dossier de bibliothèques utilisateur ici
@msg no user workspace `{from}` aucun espace de travail utilisateur `{from}`
@msg node {_1} is not text le nœud {_1} n’est pas du texte
@msg node {_1} is on a locked artboard le nœud {_1} est sur un plan de travail verrouillé
@msg not a DXF drawing ce n’est pas un dessin DXF
@msg not a VectorCraft file: {0} ce n’est pas un fichier VectorCraft : {0}
@msg not a VectorCraft shortcut set (missing `overrides`) ce n’est pas un jeu de raccourcis VectorCraft (`overrides` manquant)
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -4976,6 +4976,7 @@ imageTrace Outline Körvonal
@msg no user library folder here itt nincs felhasználói könyvtármappa
@msg no user workspace `{from}` nincs ilyen felhasználói munkaterület: `{from}`
@msg node {_1} is not text a csomópont nem szöveg: {_1}
@msg node {_1} is on a locked artboard a csomópont zárolt rajztáblán van: {_1}
@msg not a DXF drawing nem DXF-rajz
@msg not a file nem fájl
@msg not a font file nem betűtípusfájl
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -4344,6 +4344,7 @@ axis Both Entrambi
@msg no user library folder here nessuna cartella di librerie utente qui
@msg no user workspace `{from}` nessuna area di lavoro utente `{from}`
@msg node {_1} is not text il nodo {_1} non è testo
@msg node {_1} is on a locked artboard il nodo {_1} è su una tavola da disegno bloccata
@msg not a DXF drawing non è un disegno DXF
@msg not a VectorCraft file: {0} non è un file VectorCraft: {0}
@msg not a VectorCraft shortcut set (missing `overrides`) non è un set di scelte rapide VectorCraft (manca `overrides`)
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -4306,6 +4306,7 @@ swatch Bright Violet ビビッドバイオレット
@msg a key object sits on that point そのポイントにはキーオブジェクトがあります
@msg no graphic style `{name}` グラフィックスタイル `{name}` が見つかりません
@msg node {_1} is not text ノード {_1} はテキストではありません
@msg node {_1} is on a locked artboard ノード {_1} はロックされたアートボード上にあります
@msg Text Wrap: select a wrap object テキストの回り込み: 回り込みオブジェクトを選択してください
@msg layers can't be wrap objects レイヤーは回り込みオブジェクトにできません
@msg line {line}: value for `{var}` must be true or false {line} 行目: `{var}` の値には true または false を指定してください
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -4059,6 +4059,7 @@ font-technology Variable ცვლადი
@msg no user library folder here აქ მომხმარებლის ბიბლიოთეკის საქაღალდე არ არის
@msg no user workspace `{from}` მომხმარებლის სამუშაო სივრცე `{from}` არ არის
@msg node {_1} is not text კვანძი {_1} ტექსტი არ არის
@msg node {_1} is on a locked artboard კვანძი {_1} ჩაკეტილ სამუშაო დაფაზეა
@msg not a DXF drawing ეს არ არის DXF ნახაზი
@msg not a VectorCraft file: {0} ეს არ არის VectorCraft-ის ფაილი: {0}
@msg not a VectorCraft shortcut set (missing `overrides`) ეს არ არის VectorCraft-ის მალსახმობების ნაკრები (აკლია `overrides`)
Can't render this file because it is too large.
+1
View File
@@ -4233,6 +4233,7 @@ theme Appearance 외관
@msg a key object sits on that point 그 포인트에 키 개체가 있습니다
@msg no graphic style `{name}` `{name}` 그래픽 스타일이 없습니다
@msg node {_1} is not text 노드 {_1}은(는) 텍스트가 아닙니다
@msg node {_1} is on a locked artboard 노드 {_1}이(가) 잠긴 아트보드에 있습니다
@msg Text Wrap: select a wrap object 텍스트 감싸기: 감싸기 개체를 선택하세요
@msg layers can't be wrap objects 레이어는 감싸기 개체가 될 수 없습니다
@msg line {line}: value for `{var}` must be true or false {line}행: `{var}`의 값은 true 또는 false여야 합니다
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -4432,6 +4432,7 @@ imageTrace Outline Kontur
@msg no user library folder here brak folderu bibliotek użytkownika
@msg no user workspace `{from}` brak obszaru roboczego użytkownika `{from}`
@msg node {_1} is not text węzeł {_1} nie jest tekstem
@msg node {_1} is on a locked artboard węzeł {_1} jest na zablokowanym obszarze kompozycji
@msg not a DXF drawing to nie jest rysunek DXF
@msg not a VectorCraft file: {0} to nie jest plik VectorCraft: {0}
@msg not a VectorCraft shortcut set (missing `overrides`) to nie jest zestaw skrótów VectorCraft (brak `overrides`)
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -3887,6 +3887,7 @@ axis Both Ambos
@msg no user library folder here nenhuma pasta de biblioteca do usuário aqui
@msg no user workspace `{from}` nenhum espaço de trabalho do usuário `{from}`
@msg node {_1} is not text o nó {_1} não é texto
@msg node {_1} is on a locked artboard o nó {_1} está em uma prancheta bloqueada
@msg not a DXF drawing não é um desenho DXF
@msg not a VectorCraft file: {0} não é um arquivo do VectorCraft: {0}
@msg not a VectorCraft shortcut set (missing `overrides`) não é um conjunto de atalhos do VectorCraft (falta `overrides`)
Can't render this file because it contains an unexpected character in line 6 and column 47.
+1
View File
@@ -4339,6 +4339,7 @@ axis Both Оба
@msg no user library folder here здесь нет папки пользовательских библиотек
@msg no user workspace `{from}` нет пользовательской рабочей среды `{from}`
@msg node {_1} is not text узел {_1} не является текстом
@msg node {_1} is on a locked artboard узел {_1} находится на заблокированной монтажной области
@msg not a DXF drawing не является чертежом DXF
@msg not a VectorCraft file: {0} не является файлом VectorCraft: {0}
@msg not a VectorCraft shortcut set (missing `overrides`) не является набором сочетаний клавиш VectorCraft (отсутствует `overrides`)
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -4207,6 +4207,7 @@ axis Both Båda
@msg no user library folder here ingen mapp för användarbibliotek här
@msg no user workspace `{from}` ingen användararbetslayout `{from}`
@msg node {_1} is not text nod {_1} är inte text
@msg node {_1} is on a locked artboard nod {_1} ligger på en låst rityta
@msg not a DXF drawing inte en DXF-ritning
@msg not a VectorCraft file: {0} inte en VectorCraft-fil: {0}
@msg not a VectorCraft shortcut set (missing `overrides`) inte en kortkommandouppsättning för VectorCraft (`overrides` saknas)
Can't render this file because it contains an unexpected character in line 5 and column 25.
+1
View File
@@ -4062,6 +4062,7 @@ axis Both Her İkisi
@msg no user library folder here burada kullanıcı kitaplığı klasörü yok
@msg no user workspace `{from}` kullanıcı çalışma alanı yok `{from}`
@msg node {_1} is not text {_1} düğümü metin değil
@msg node {_1} is on a locked artboard {_1} düğümü kilitli bir çalışma yüzeyinde
@msg not a DXF drawing DXF çizimi değil
@msg not a VectorCraft file: {0} bir VectorCraft dosyası değil: {0}
@msg not a VectorCraft shortcut set (missing `overrides`) VectorCraft kısayol seti değil ("geçersiz kılmalar" eksik)
Can't render this file because it contains an unexpected character in line 5 and column 25.
+1
View File
@@ -4328,6 +4328,7 @@ axis Both Обидві
@msg no user library folder here тут немає папки користувацьких бібліотек
@msg no user workspace `{from}` немає користувача робочого середовища `{from}`
@msg node {_1} is not text вузол {_1} не є текстом
@msg node {_1} is on a locked artboard вузол {_1} розташований на заблокованій монтажній області
@msg not a DXF drawing не є кресленням DXF
@msg not a VectorCraft file: {0} не є файлом VectorCraft: {0}
@msg not a VectorCraft shortcut set (missing `overrides`) не є набором поєднань клавіш VectorCraft (відсутнє `overrides`)
Can't render this file because it contains an unexpected character in line 177 and column 5.
+1
View File
@@ -4628,6 +4628,7 @@ theme Appearance Giao diện
@msg no user library folder here không có thư mục thư viện người dùng ở đây
@msg no user workspace `{from}` không có không gian làm việc người dùng `{from}`
@msg node {_1} is not text nút {_1} không phải là văn bản
@msg node {_1} is on a locked artboard nút {_1} nằm trên bảng vẽ bị khóa
@msg not a blend không phải đối tượng hòa trộn
@msg not a DXF drawing không phải bản vẽ DXF
@msg not a file không phải tệp
Can't render this file because it contains an unexpected character in line 199 and column 5.
+1
View File
@@ -4031,6 +4031,7 @@ imageTrace Outline 轮廓
@msg a graphic style named `{to}` already exists 名为 `{to}` 的图形样式已存在
@msg no graphic style `{name}` 没有图形样式 `{name}`
@msg node {_1} is not text 节点 {_1} 不是文字
@msg node {_1} is on a locked artboard 节点 {_1} 位于已锁定的画板上
@msg Text Wrap: select a wrap object 文本绕排:请选择一个绕排对象
@msg layers can't be wrap objects 图层不能作为绕排对象
@msg line {line}: value for `{var}` must be true or false 第 {line} 行:`{var}` 的值必须是 true 或 false
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -1938,6 +1938,7 @@ file-filter Templates 範本
@msg a graphic style named `{to}` already exists 名為 `{to}` 的繪圖樣式已存在
@msg no graphic style `{name}` 沒有繪圖樣式 `{name}`
@msg node {_1} is not text 節點 {_1} 不是文字
@msg node {_1} is on a locked artboard 節點 {_1} 位於已鎖定的工作區域上
@msg Text Wrap: select a wrap object 文字繞圖:請選取繞圖物件
@msg layers can't be wrap objects 圖層不能作為繞圖物件
@msg line {line}: value for `{var}` must be true or false 第 {line} 行:`{var}` 的值必須是 true 或 false
Can't render this file because it contains an unexpected character in line 6 and column 47.
+2 -2
View File
@@ -1813,7 +1813,7 @@ document stays unmodified.
`dataset.select`, `dataset.next` and `dataset.prev` reply `{name, applied, skipped}`. They add `overflow: [id…]`
when area type or type on a path whose text they rewrote doesn't fit, as `text.setText` does (see
[Fitting area type](#fitting-area-type-auto-size-shrink-text-to-fit-overflow)). They skip an object that is
locked or inside a locked layer or group, and count it in `skipped`. They rewrite hidden objects and objects inside
locked, inside a locked layer or group, or on a locked artboard, and count it in `skipped`. They rewrite hidden objects and objects inside
a hidden layer or group, which stay hidden unless one of the data set's visibility values shows them. When such a
layer is shown again, its type holds the data set's text. They apply the values in the order the variables are
defined. Of two variables of the same kind on one object, the one defined last wins. `dataset.list`,
@@ -1848,7 +1848,7 @@ or no, or a graph value longer than 262,144 bytes.
`dataset.update {all?}` writes what the bound objects hold now into the active data set, for each variable that the
data set holds. A variable whose objects report no value, because they are locked, inside a locked layer or group,
or deleted, keeps the data set's value. With `all: true` it also adds every other variable that the
on a locked artboard, or deleted, keeps the data set's value. With `all: true` it also adds every other variable that the
objects report a value for. The reply gives `values`, the number of values it wrote, and `left`, the variables it
did not write. When every bound object is locked, it writes no value and adds no undo step, and `dataset.capture`
returns the error "no bound object reports a value (locked objects and embedded images report none)".