Skip to content

Commit 1dbea96

Browse files
authored
Merge branch 'master' into redo-transparent-bg-render
2 parents 5d44cca + 7bb01c9 commit 1dbea96

37 files changed

Lines changed: 2127 additions & 327 deletions

File tree

.github/workflows/build.yml

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,12 +153,18 @@ jobs:
153153
if [ "${{ github.ref }}" = "refs/tags/latest-stable" ]; then
154154
REF="latest-stable"
155155
ENVIRONMENT="graphite-editor (Production)"
156+
AUTO_INACTIVE="true"
157+
TRANSIENT_ENVIRONMENT="false"
156158
elif [ "${{ github.event_name }}" = "push" ]; then
157159
REF="master"
158160
ENVIRONMENT="graphite-dev (Production)"
161+
AUTO_INACTIVE="true"
162+
TRANSIENT_ENVIRONMENT="false"
159163
else
160164
REF="${{ inputs.checkout_ref || github.head_ref || github.ref_name }}"
161165
ENVIRONMENT="graphite-dev (Preview)"
166+
AUTO_INACTIVE="false"
167+
TRANSIENT_ENVIRONMENT="true"
162168
fi
163169
create_deployment() {
164170
gh api \
@@ -167,7 +173,14 @@ jobs:
167173
repos/${{ github.repository }}/deployments \
168174
--input - \
169175
--jq '.id' <<EOF
170-
{"ref":"$1","environment":"$ENVIRONMENT","auto_merge":false,"required_contexts":[]}
176+
{
177+
"ref": "$1",
178+
"environment": "$ENVIRONMENT",
179+
"auto_merge": false,
180+
"required_contexts": [],
181+
"auto_inactive": $AUTO_INACTIVE,
182+
"transient_environment": $TRANSIENT_ENVIRONMENT
183+
}
171184
EOF
172185
}
173186
# Try branch name first (needed for GitHub's PR "View deployment" button), fall back to commit SHA if the branch was deleted
@@ -191,9 +204,19 @@ jobs:
191204
exit 0
192205
fi
193206
207+
size_of() { find frontend/dist/assets "$@" -printf '%s\n' | awk '{s+=$1} END {printf "%.2f MB", s/1048576}'; }
208+
WASM_SIZE=$(size_of -name '*.wasm')
209+
JS_SIZE=$(size_of -name '*.js')
210+
CSS_SIZE=$(size_of -name '*.css')
211+
FONT_SIZE=$(size_of \( -name '*.woff2' -o -name '*.woff' -o -name '*.ttf' -o -name '*.otf' \))
212+
IMAGE_SIZE=$(size_of \( -name '*.png' -o -name '*.jpg' -o -name '*.svg' \))
213+
ALL_SIZE=$(size_of -type f)
214+
194215
COMMENT_BODY="| 📦 **Web Build Complete for** $(git rev-parse HEAD) |
195216
|-|
196-
| $CF_URL |"
217+
| $CF_URL |
218+
219+
Wasm: **$WASM_SIZE** — JS: **$JS_SIZE** — CSS: **$CSS_SIZE** — Fonts: **$FONT_SIZE** — Images: **$IMAGE_SIZE** — All Assets: **$ALL_SIZE**"
197220
198221
if [ "${{ github.ref }}" = "refs/tags/latest-stable" ]; then
199222
# Push tag: skip commenting (commit was already commented on master merge)

Cargo.lock

Lines changed: 31 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@ log = "0.4"
106106
bitflags = { version = "2.4", features = ["serde"] }
107107
ctor = "0.2"
108108
convert_case = "0.8"
109+
titlecase = "3.6"
110+
fancy-regex = "0.18.0"
111+
unicode-segmentation = "1.13.2"
109112
indoc = "2.0.5"
110113
derivative = "2.2"
111114
thiserror = "2"

editor/src/messages/layout/utility_types/widgets/input_widgets.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,7 @@ pub struct TextAreaInput {
362362
pub value: String,
363363
pub label: Option<String>,
364364
pub disabled: bool,
365+
pub monospace: bool,
365366

366367
// Tooltips
367368
#[serde(rename = "tooltipLabel")]

editor/src/messages/portfolio/document/data_panel/data_panel_message_handler.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -584,7 +584,7 @@ impl TableRowLayout for f64 {
584584
"Number (f64)".to_string()
585585
}
586586
fn element_page(&self, _data: &mut LayoutData) -> Vec<LayoutGroup> {
587-
let widgets = vec![TextLabel::new(self.to_string()).widget_instance()];
587+
let widgets = vec![NumberInput::new(Some(*self)).disabled(true).max_width(220).display_decimal_places(20).widget_instance()];
588588
vec![LayoutGroup::row(widgets)]
589589
}
590590
}
@@ -597,7 +597,7 @@ impl TableRowLayout for u32 {
597597
"Number (u32)".to_string()
598598
}
599599
fn element_page(&self, _data: &mut LayoutData) -> Vec<LayoutGroup> {
600-
let widgets = vec![TextLabel::new(self.to_string()).widget_instance()];
600+
let widgets = vec![NumberInput::new(Some(*self as f64)).disabled(true).max_width(220).display_decimal_places(20).widget_instance()];
601601
vec![LayoutGroup::row(widgets)]
602602
}
603603
}
@@ -610,7 +610,8 @@ impl TableRowLayout for u64 {
610610
"Number (u64)".to_string()
611611
}
612612
fn element_page(&self, _data: &mut LayoutData) -> Vec<LayoutGroup> {
613-
let widgets = vec![TextLabel::new(self.to_string()).widget_instance()];
613+
// TODO: Make this robust for large u64 values that don't fit in f64 (above roughly 2^53). Perhaps using a bigint kind of approach through the widget's data flow.
614+
let widgets = vec![NumberInput::new(Some(*self as f64)).disabled(true).max_width(220).display_decimal_places(20).widget_instance()];
614615
vec![LayoutGroup::row(widgets)]
615616
}
616617
}
@@ -642,7 +643,7 @@ impl TableRowLayout for String {
642643
}
643644
}
644645
fn element_page(&self, _data: &mut LayoutData) -> Vec<LayoutGroup> {
645-
let widgets = vec![TextAreaInput::new(self.to_string()).disabled(true).widget_instance()];
646+
let widgets = vec![TextAreaInput::new(self.to_string()).monospace(true).disabled(true).widget_instance()];
646647
vec![LayoutGroup::row(widgets)]
647648
}
648649
}

editor/src/messages/portfolio/document/node_graph/document_node_definitions.rs

Lines changed: 110 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,7 @@ fn document_node_definitions() -> HashMap<DefinitionIdentifier, DocumentNodeDefi
537537
},
538538
// 11: Switch (closed → count, open → max(count - 1, 1) as denominator)
539539
DocumentNode {
540-
implementation: DocumentNodeImplementation::ProtoNode(logic::switch::IDENTIFIER),
540+
implementation: DocumentNodeImplementation::ProtoNode(math_nodes::switch::IDENTIFIER),
541541
inputs: vec![NodeInput::node(NodeId(10), 0), NodeInput::node(NodeId(17), 0), NodeInput::node(NodeId(18), 0)],
542542
..Default::default()
543543
},
@@ -1489,6 +1489,113 @@ fn document_node_definitions() -> HashMap<DefinitionIdentifier, DocumentNodeDefi
14891489
description: Cow::Borrowed("TODO"),
14901490
properties: None,
14911491
},
1492+
DocumentNodeDefinition {
1493+
identifier: "Regex Find",
1494+
category: "Text: Regex",
1495+
node_template: NodeTemplate {
1496+
document_node: DocumentNode {
1497+
implementation: DocumentNodeImplementation::Network(NodeNetwork {
1498+
exports: vec![
1499+
// Primary output: the whole match (String)
1500+
NodeInput::node(NodeId(1), 0),
1501+
// Secondary output: capture groups (Vec<String>)
1502+
NodeInput::node(NodeId(2), 0),
1503+
],
1504+
nodes: [
1505+
// Node 0: regex_find proto node — returns Vec<String> of [whole_match, ...capture_groups]
1506+
DocumentNode {
1507+
inputs: vec![
1508+
NodeInput::import(concrete!(String), 0),
1509+
NodeInput::import(concrete!(String), 1),
1510+
NodeInput::import(concrete!(f64), 2),
1511+
NodeInput::import(concrete!(bool), 3),
1512+
NodeInput::import(concrete!(bool), 4),
1513+
],
1514+
implementation: DocumentNodeImplementation::ProtoNode(text_nodes::regex::regex_find::IDENTIFIER),
1515+
..Default::default()
1516+
},
1517+
// Node 1: index_elements at index 0 — extracts the whole match as a String
1518+
DocumentNode {
1519+
inputs: vec![NodeInput::node(NodeId(0), 0), NodeInput::value(TaggedValue::F64(0.), false)],
1520+
implementation: DocumentNodeImplementation::ProtoNode(graphic::index_elements::IDENTIFIER),
1521+
..Default::default()
1522+
},
1523+
// Node 2: omit_element at index 0 — returns capture groups as Vec<String>
1524+
DocumentNode {
1525+
inputs: vec![NodeInput::node(NodeId(0), 0), NodeInput::value(TaggedValue::F64(0.), false)],
1526+
implementation: DocumentNodeImplementation::ProtoNode(graphic::omit_element::IDENTIFIER),
1527+
..Default::default()
1528+
},
1529+
]
1530+
.into_iter()
1531+
.enumerate()
1532+
.map(|(id, node)| (NodeId(id as u64), node))
1533+
.collect(),
1534+
..Default::default()
1535+
}),
1536+
inputs: vec![
1537+
NodeInput::value(TaggedValue::String(String::new()), true),
1538+
NodeInput::value(TaggedValue::String(String::new()), false),
1539+
NodeInput::value(TaggedValue::F64(0.), false),
1540+
NodeInput::value(TaggedValue::Bool(false), false),
1541+
NodeInput::value(TaggedValue::Bool(false), false),
1542+
],
1543+
..Default::default()
1544+
},
1545+
persistent_node_metadata: DocumentNodePersistentMetadata {
1546+
input_metadata: vec![
1547+
("String", "The string to search within.").into(),
1548+
("Pattern", "The regular expression pattern to search for.").into(),
1549+
(
1550+
"Match Index",
1551+
"Which non-overlapping occurrence of the pattern to return, starting from 0 for the first match. Negative indices count backwards from the last match.",
1552+
)
1553+
.into(),
1554+
("Case Insensitive", "Match letters regardless of case.").into(),
1555+
("Multiline", "Make `^` and `$` match the start and end of each line, not just the whole string.").into(),
1556+
],
1557+
output_names: vec!["Match".to_string(), "Captures".to_string()],
1558+
network_metadata: Some(NodeNetworkMetadata {
1559+
persistent_metadata: NodeNetworkPersistentMetadata {
1560+
node_metadata: [
1561+
DocumentNodeMetadata {
1562+
persistent_metadata: DocumentNodePersistentMetadata {
1563+
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(0, 0)),
1564+
..Default::default()
1565+
},
1566+
..Default::default()
1567+
},
1568+
DocumentNodeMetadata {
1569+
persistent_metadata: DocumentNodePersistentMetadata {
1570+
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(8, 0)),
1571+
..Default::default()
1572+
},
1573+
..Default::default()
1574+
},
1575+
DocumentNodeMetadata {
1576+
persistent_metadata: DocumentNodePersistentMetadata {
1577+
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(8, 2)),
1578+
..Default::default()
1579+
},
1580+
..Default::default()
1581+
},
1582+
]
1583+
.into_iter()
1584+
.enumerate()
1585+
.map(|(id, node)| (NodeId(id as u64), node))
1586+
.collect(),
1587+
..Default::default()
1588+
},
1589+
..Default::default()
1590+
}),
1591+
..Default::default()
1592+
},
1593+
},
1594+
description: Cow::Borrowed(
1595+
r#"Finds a portion of the string matching a regular expression pattern. With "Match Index" at its default 0, it selects the first non-overlapping occurrence, but others may be selected. Capture groups, if any, are produced as a list in the "Captures" output."#,
1596+
),
1597+
properties: None,
1598+
},
14921599
// Aims for interoperable compatibility with:
14931600
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=levl%27%20%3D%20Levels-,%27curv%27%20%3D%20Curves,-%27expA%27%20%3D%20Exposure
14941601
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=Max%20input%20range-,Curves,-Curves%20settings%20files
@@ -2035,6 +2142,8 @@ fn static_node_properties() -> NodeProperties {
20352142
map.insert("selective_color_properties".to_string(), Box::new(node_properties::selective_color_properties));
20362143
map.insert("exposure_properties".to_string(), Box::new(node_properties::exposure_properties));
20372144
map.insert("math_properties".to_string(), Box::new(node_properties::math_properties));
2145+
map.insert("format_number_properties".to_string(), Box::new(node_properties::format_number_properties));
2146+
map.insert("string_capitalization_properties".to_string(), Box::new(node_properties::string_capitalization_properties));
20382147
map.insert("rectangle_properties".to_string(), Box::new(node_properties::rectangle_properties));
20392148
map.insert("grid_properties".to_string(), Box::new(node_properties::grid_properties));
20402149
map.insert("spiral_properties".to_string(), Box::new(node_properties::spiral_properties));

0 commit comments

Comments
 (0)