wayver's git archive


an obsidian renderer
git clone https://git.wayver.dev/sable

sable-vault/src/canvas.rs@2b84405277e54ab809e328cf0237374d4b4dbd0c

raw
Date Commit Message Author Files + -
2026-02-23 01:55 initial mvp wayverd 139 17808 0
...

1use std::collections::HashMap;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
4pub enum PresetColor {
5    #[serde(rename = "1")]
6    Red = 1,
7    #[serde(rename = "2")]
8    Orange = 2,
9    #[serde(rename = "3")]
10    Yellow = 3,
11    #[serde(rename = "4")]
12    Green = 4,
13    #[serde(rename = "5")]
14    Cyan = 5,
15    #[serde(rename = "6")]
16    Purple = 6,
17}
18
19#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
20#[serde(untagged)]
21pub enum Color {
22    Preset(PresetColor),
23    Color(HexColor),
24}
25
26#[derive(Debug, Clone, Hash, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
27#[repr(transparent)]
28#[serde(transparent)]
29pub struct EdgeId(pub(self) String);
30
31#[derive(Debug, Clone, Hash, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
32#[repr(transparent)]
33#[serde(transparent)]
34pub struct NodeId(pub(self) String);
35
36#[derive(Debug, Default, serde::Serialize, serde::Deserialize)]
37pub struct JsonCanvas {
38    #[serde(
39        serialize_with = "serialize_as_vec_node",
40        deserialize_with = "deserialize_as_map_node"
41    )]
42    #[serde(skip_serializing_if = "HashMap::is_empty", default)]
43    nodes: HashMap<NodeId, Node>,
44
45    #[serde(
46        serialize_with = "serialize_as_vec_edge",
47        deserialize_with = "deserialize_as_map_edge"
48    )]
49    #[serde(skip_serializing_if = "HashMap::is_empty", default)]
50    edges: HashMap<EdgeId, Edge>,
51}
52
53#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
54#[serde(rename_all = "camelCase")]
55pub struct Edge {
56    pub id: EdgeId,
57
58    #[serde(skip_serializing_if = "Option::is_none")]
59    color: Option<Color>,
60    #[serde(skip_serializing_if = "Option::is_none")]
61    label: Option<String>,
62
63    pub from_node: NodeId,
64    pub to_node: NodeId,
65
66    #[serde(skip_serializing_if = "Option::is_none")]
67    from_side: Option<EdgeSide>,
68    #[serde(skip_serializing_if = "Option::is_none")]
69    to_side: Option<EdgeSide>,
70
71    #[serde(skip_serializing_if = "Option::is_none")]
72    from_end: Option<EdgeEnd>,
73    #[serde(skip_serializing_if = "Option::is_none")]
74    to_end: Option<EdgeEnd>,
75}
76
77#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize)]
78#[serde(rename_all = "camelCase")]
79pub enum EdgeSide {
80    Top,
81    Left,
82    Right,
83    Bottom,
84}
85
86#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize)]
87#[serde(rename_all = "camelCase")]
88pub enum EdgeEnd {
89    None,
90    Arrow,
91}
92