mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-19 19:08:05 +08:00
Migrate remaining node graph data types from Vec to Table (#4067)
* Move Vec<String> to Table<String> * Remove old VecDVec2 * Move Vec<u8> to Table<u8> * Move Vec<f64> to Table<f64> * Move [f64; 4] to Table<f64> * Move Vec<NodeId> to Table<NodeId> * Tidy up the TaggedValue variants * Move Vec<BrushStroke> to Table<BrushStroke> * Add missing type implementations * Fix tests ---------
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
use core_types::Ctx;
|
||||
use core_types::table::{Table, TableRow};
|
||||
use serde_json::Value;
|
||||
|
||||
use crate::unescape_string;
|
||||
@@ -237,15 +238,15 @@ fn query_json_all(
|
||||
/// Strips the surrounding double quotes from string values, returning the raw text. Other types are never wrapped in quotes.
|
||||
#[default(true)]
|
||||
unquote_strings: bool,
|
||||
) -> Vec<String> {
|
||||
) -> Table<String> {
|
||||
let cleaned = strip_trailing_commas(&json);
|
||||
let Ok(value): Result<Value, _> = serde_json::from_str(&cleaned) else { return Vec::new() };
|
||||
let Some(segments) = parse_json_path(path.trim()) else { return Vec::new() };
|
||||
let Ok(value): Result<Value, _> = serde_json::from_str(&cleaned) else { return Table::new() };
|
||||
let Some(segments) = parse_json_path(path.trim()) else { return Table::new() };
|
||||
|
||||
let mut results = Vec::new();
|
||||
resolve_all(&value, &segments, !unquote_strings, &mut results);
|
||||
|
||||
results
|
||||
results.into_iter().map(TableRow::new_from_element).collect()
|
||||
}
|
||||
|
||||
/// A parsed segment of a JSON access path.
|
||||
|
||||
@@ -9,7 +9,7 @@ use convert_case::{Boundary, Converter, pattern};
|
||||
use core_types::Color;
|
||||
use core_types::graphene_hash::CacheHash;
|
||||
use core_types::registry::types::{SignedInteger, TextArea};
|
||||
use core_types::table::Table;
|
||||
use core_types::table::{Table, TableRow};
|
||||
use core_types::{CloneVarArgs, Context, Ctx, ExtractAll, ExtractVarArgs, OwnedContextImpl};
|
||||
use dyn_any::DynAny;
|
||||
use glam::{DAffine2, DVec2};
|
||||
@@ -700,10 +700,10 @@ fn string_split(
|
||||
/// "\n" (newline), "\r" (carriage return), "\t" (tab), "\0" (null), and "\\" (backslash).
|
||||
#[default(true)]
|
||||
delimiter_escaping: bool,
|
||||
) -> Vec<String> {
|
||||
) -> Table<String> {
|
||||
let delimiter = if delimiter_escaping { unescape_string(delimiter) } else { delimiter };
|
||||
|
||||
string.split(&delimiter).map(str::to_string).collect()
|
||||
string.split(&delimiter).map(str::to_string).map(TableRow::new_from_element).collect()
|
||||
}
|
||||
|
||||
/// Joins a list of strings together with a separator between each pair. This is the inverse of the **String Split** node.
|
||||
@@ -713,7 +713,7 @@ fn string_split(
|
||||
fn string_join(
|
||||
_: impl Ctx,
|
||||
/// The list of strings to join together.
|
||||
strings: Vec<String>,
|
||||
strings: Table<String>,
|
||||
/// The text placed between each pair of strings.
|
||||
#[default(", ")]
|
||||
separator: String,
|
||||
@@ -724,26 +724,27 @@ fn string_join(
|
||||
) -> String {
|
||||
let separator = if separator_escaping { unescape_string(separator) } else { separator };
|
||||
|
||||
strings.join(&separator)
|
||||
strings.iter_element_values().map(|s| s.as_str()).collect::<Vec<_>>().join(&separator)
|
||||
}
|
||||
|
||||
/// Iterates over a list of strings, evaluating the mapped operation for each one. Use the **Read String** node to access the current string inside the loop.
|
||||
#[node_macro::node(category("Text"))]
|
||||
async fn map_string(
|
||||
ctx: impl Ctx + CloneVarArgs + ExtractAll,
|
||||
strings: Vec<String>,
|
||||
strings: Table<String>,
|
||||
#[expose]
|
||||
#[implementations(Context -> String)]
|
||||
mapped: impl Node<Context<'static>, Output = String>,
|
||||
) -> Vec<String> {
|
||||
let mut result = Vec::new();
|
||||
) -> Table<String> {
|
||||
let mut result = Table::new();
|
||||
|
||||
for (i, string) in strings.into_iter().enumerate() {
|
||||
for (i, row) in strings.into_iter().enumerate() {
|
||||
let string = row.into_element();
|
||||
let owned_ctx = OwnedContextImpl::from(ctx.clone());
|
||||
let owned_ctx = owned_ctx.with_vararg(Box::new(string)).with_index(i);
|
||||
let mapped_strings = mapped.eval(owned_ctx.into_context()).await;
|
||||
let mapped_string = mapped.eval(owned_ctx.into_context()).await;
|
||||
|
||||
result.push(mapped_strings);
|
||||
result.push(TableRow::new_from_element(mapped_string));
|
||||
}
|
||||
|
||||
result
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use core_types::Ctx;
|
||||
use core_types::registry::types::SignedInteger;
|
||||
use core_types::table::{Table, TableRow};
|
||||
|
||||
/// Checks whether the string contains a match for the given regular expression pattern. Optionally restricts the match to only the start and/or end of the string.
|
||||
#[node_macro::node(category("Text: Regex"))]
|
||||
@@ -92,9 +93,9 @@ fn regex_find(
|
||||
case_insensitive: bool,
|
||||
/// Make `^` and `$` match the start and end of each line, not just the whole string.
|
||||
multiline: bool,
|
||||
) -> Vec<String> {
|
||||
) -> Table<String> {
|
||||
if pattern.is_empty() {
|
||||
return Vec::new();
|
||||
return Table::new();
|
||||
}
|
||||
|
||||
let flags = match (case_insensitive, multiline) {
|
||||
@@ -107,7 +108,7 @@ fn regex_find(
|
||||
|
||||
let Ok(regex) = fancy_regex::Regex::new(&full_pattern) else {
|
||||
log::error!("Invalid regex pattern: {pattern}");
|
||||
return Vec::new();
|
||||
return Table::new();
|
||||
};
|
||||
|
||||
// Collect all matches since we need to support negative indexing
|
||||
@@ -117,7 +118,7 @@ fn regex_find(
|
||||
let resolved_index = if match_index < 0 {
|
||||
let from_end = (-match_index) as usize;
|
||||
if from_end > matches.len() {
|
||||
return Vec::new();
|
||||
return Table::new();
|
||||
}
|
||||
matches.len() - from_end
|
||||
} else {
|
||||
@@ -125,11 +126,14 @@ fn regex_find(
|
||||
};
|
||||
|
||||
let Some(captures) = matches.get(resolved_index) else {
|
||||
return Vec::new();
|
||||
return Table::new();
|
||||
};
|
||||
|
||||
// Index 0 is the whole match, 1+ are capture groups
|
||||
(0..captures.len()).map(|i| captures.get(i).map_or(String::new(), |m| m.as_str().to_string())).collect()
|
||||
(0..captures.len())
|
||||
.map(|i| captures.get(i).map_or(String::new(), |m| m.as_str().to_string()))
|
||||
.map(TableRow::new_from_element)
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Finds all non-overlapping matches of a regular expression pattern in the string, returning a list of the matched substrings.
|
||||
@@ -144,9 +148,9 @@ fn regex_find_all(
|
||||
case_insensitive: bool,
|
||||
/// Make `^` and `$` match the start and end of each line, not just the whole string.
|
||||
multiline: bool,
|
||||
) -> Vec<String> {
|
||||
) -> Table<String> {
|
||||
if pattern.is_empty() {
|
||||
return Vec::new();
|
||||
return Table::new();
|
||||
}
|
||||
|
||||
let flags = match (case_insensitive, multiline) {
|
||||
@@ -159,10 +163,15 @@ fn regex_find_all(
|
||||
|
||||
let Ok(regex) = fancy_regex::Regex::new(&full_pattern) else {
|
||||
log::error!("Invalid regex pattern: {pattern}");
|
||||
return Vec::new();
|
||||
return Table::new();
|
||||
};
|
||||
|
||||
regex.find_iter(&string).filter_map(|m| m.ok()).map(|m| m.as_str().to_string()).collect()
|
||||
regex
|
||||
.find_iter(&string)
|
||||
.filter_map(|m| m.ok())
|
||||
.map(|m| m.as_str().to_string())
|
||||
.map(TableRow::new_from_element)
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Splits a string into a list of substrings pulled from between separator characters as matched by a regular expression.
|
||||
@@ -179,9 +188,9 @@ fn regex_split(
|
||||
case_insensitive: bool,
|
||||
/// Make `^` and `$` match the start and end of each line, not just the whole string.
|
||||
multiline: bool,
|
||||
) -> Vec<String> {
|
||||
) -> Table<String> {
|
||||
if pattern.is_empty() {
|
||||
return vec![string];
|
||||
return Table::new_from_element(string);
|
||||
}
|
||||
|
||||
let flags = match (case_insensitive, multiline) {
|
||||
@@ -194,8 +203,8 @@ fn regex_split(
|
||||
|
||||
let Ok(regex) = fancy_regex::Regex::new(&full_pattern) else {
|
||||
log::error!("Invalid regex pattern: {pattern}");
|
||||
return vec![string];
|
||||
return Table::new_from_element(string);
|
||||
};
|
||||
|
||||
regex.split(&string).filter_map(|s| s.ok()).map(|s| s.to_string()).collect()
|
||||
regex.split(&string).filter_map(|s| s.ok()).map(|s| s.to_string()).map(TableRow::new_from_element).collect()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user