Add files via upload

This commit is contained in:
mortezanaeemi-ops authored and GitHub committed 2026-11-01 14:54:48 +03:30
1 parent 08537cf425
commit 5d4a5082ec
2 files changed
+51 -7

No files matched your search

+12 -4
View File
@@ -427,6 +427,8 @@ fn version_rank(v: &str) -> (u64, u64) {
pub(super) struct VarCanon {
by_key: HashMap<String, String>,
by_id: HashMap<String, String>,
/// Every live variable node of the file, with a key or not.
local: BTreeSet<String>,
}
thread_local! {
@@ -446,10 +448,12 @@ impl VarCanon {
fn install(m: &Mapper) -> VarCanonGuard {
let mut newest: HashMap<String, ((u64, u64), String)> = HashMap::new();
let mut copies: Vec<(String, String)> = Vec::new();
let mut local = BTreeSet::new();
for (id, n) in &m.nodes {
if n.get("type").and_then(Kv::str) != Some("VARIABLE") || n.get("isSoftDeleted").and_then(Kv::bool) == Some(true) {
continue;
}
local.insert(id.clone());
let Some(key) = n.get("key").and_then(Kv::str).filter(|k| !k.is_empty()) else { continue };
let rank = version_rank(n.get("version").and_then(Kv::str).unwrap_or(""));
copies.push((id.clone(), key.to_string()));
@@ -465,21 +469,25 @@ impl VarCanon {
}
}
t.by_key = newest.into_iter().map(|(k, (_, id))| (k, id)).collect();
t.local = local;
VAR_CANON.with(|c| *c.borrow_mut() = Some(t));
VarCanonGuard
}
/// The variable a reference (`{guid}` or `{assetRef}`) names, as its newest copy.
/// The variable a reference (`{guid}` or `{assetRef}`) names, as its newest copy. A guid
/// counts when this file holds a variable by it; one from another file (a paste carries the
/// library's own guids) names nothing here, so the asset it also names is tried before it is
/// kept as it is.
pub(super) fn resolve(r: &Kv) -> Option<String> {
let by_guid = r.get("guid").and_then(guid).filter(|g| g != NO_STYLE);
VAR_CANON.with(|c| {
let c = c.borrow();
let Some(t) = c.as_ref() else { return by_guid.clone() };
if let Some(g) = &by_guid {
if let Some(g) = by_guid.as_ref().filter(|g| t.local.contains(*g)) {
return Some(t.by_id.get(g).cloned().unwrap_or_else(|| g.clone()));
}
let key = r.get("assetRef")?.get("key").and_then(Kv::str)?;
t.by_key.get(key).cloned()
let by_asset = r.get("assetRef").and_then(|a| a.get("key")).and_then(Kv::str).and_then(|k| t.by_key.get(k)).cloned();
by_asset.or(by_guid)
})
}
+39 -3
View File
@@ -1522,7 +1522,8 @@ fn library_copies_of_several_versions_become_the_newest() {
Some((2, "!")),
"VARIABLE_SET",
"Products",
vec![("variableSetModes", arr(vec![mode(90, "Blue", "!")])), ("key", s("products")), ("version", s("10:1"))],
// "Legacy" was removed from the library since: only this older copy has it.
vec![("variableSetModes", arr(vec![mode(90, "Blue", "!"), mode(93, "Legacy", "\"")])), ("key", s("products")), ("version", s("10:1"))],
),
node(
6,
@@ -1557,6 +1558,37 @@ fn library_copies_of_several_versions_become_the_newest() {
("version", s("20:1")),
],
),
// A pasted layer names the variable by the library's own guid (not a node of this file)
// and by its asset: the asset wins.
node(
11,
Some((1, "\"")),
"FRAME",
"Pasted button",
vec![
("size", xy(100.0, 40.0)),
(
"fillPaints",
arr(vec![o(vec![
("type", e("SOLID")),
("color", rgb(0.0, 0.0, 1.0)),
(
"colorVar",
o(vec![
(
"value",
o(vec![(
"alias",
o(vec![("guid", g(777)), ("assetRef", o(vec![("key", s("button-bg")), ("version", s("20:1"))]))]),
)]),
),
("dataType", e("ALIAS")),
]),
),
])]),
),
],
),
// The button names the older copy of the variable.
node(
10,
@@ -1575,14 +1607,18 @@ fn library_copies_of_several_versions_become_the_newest() {
let (doc, warnings) = import(&canvas(&schema(), &o(vec![("nodeChanges", arr(nodes))])), "x").unwrap();
assert_eq!(doc.variables.collections.len(), 1, "{:?}", doc.variables.collections);
let products = &doc.variables.collections[0];
assert_eq!(products.modes.iter().map(|m| m.name.as_str()).collect::<Vec<_>>(), ["Blue", "Purple"]);
assert_eq!(products.modes.iter().map(|m| m.name.as_str()).collect::<Vec<_>>(), ["Blue", "Purple", "Legacy"]);
assert_eq!(doc.variables.variables.len(), 1);
let var = &doc.variables.variables[0];
assert_eq!(var.collection, products.id);
assert_eq!(var.values.len(), 2, "the newest copy's values: {:?}", var.values);
// The newest copy's values: Purple included (a mode only it has), Legacy filled from the default.
assert_eq!(var.values.len(), 3, "{:?}", var.values);
assert!(matches!(var.values.get("1:92"), Some(figcraft_doc::VariableValue::Color(c)) if (c.r - 0.5).abs() < 1e-6), "{:?}", var.values);
let page = doc.nodes().find(|n| n.name == "Page").unwrap();
assert_eq!(page.var_modes.get(&products.id).map(String::as_str), Some("1:92"));
let button = named(&doc, "Button");
assert_eq!(button.bound.values().next(), Some(&var.id), "{:?}", button.bound);
let pasted = named(&doc, "Pasted button");
assert_eq!(pasted.bound.values().next(), Some(&var.id), "{:?}", pasted.bound);
assert!(!warnings.iter().any(|w| w.contains("variable modes of collections")), "{warnings:?}");
}