From 4a5efe94d9b1b2ec8de7ff6c655cc78c9a094efb Mon Sep 17 00:00:00 2001
From: Azriel Hoh
Date: Sat, 12 Apr 2025 13:31:57 +1200
Subject: [PATCH 01/17] Update github actions' versions.
---
.github/workflows/ci.yml | 6 ++++--
.github/workflows/publish.yml | 33 +++++++++++++++------------------
2 files changed, 19 insertions(+), 20 deletions(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 3fadddc..bb2f03d 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -15,7 +15,9 @@ jobs:
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- - uses: actions-rust-lang/audit@v1
+ - name: "Generate Cargo.lock"
+ run: cargo generate-lockfile
+ - uses: actions-rust-lang/audit@v2
name: Audit Rust Dependencies
with:
denyWarnings: true
@@ -111,7 +113,7 @@ jobs:
run: du -sh target/coverage target/llvm-cov-target
- name: Upload to codecov.io
- uses: codecov/codecov-action@v4
+ uses: codecov/codecov-action@v5
with:
files: ./target/coverage/lcov.info
token: ${{ secrets.CODECOV_TOKEN }}
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index ca2d860..239d2b2 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -12,7 +12,9 @@ jobs:
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- - uses: actions-rust-lang/audit@v1
+ - name: "Generate Cargo.lock"
+ run: cargo generate-lockfile
+ - uses: actions-rust-lang/audit@v2
name: Audit Rust Dependencies
with:
denyWarnings: true
@@ -56,34 +58,29 @@ jobs:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- - name: cargo-release Cache
- id: cargo_release_cache
- uses: actions/cache@v4
+ - name: cargo-release cache restore
+ id: cargo_release_cache_restore
+ uses: actions/cache/restore@v4
with:
path: ~/.cargo/bin/cargo-release
key: ${{ runner.os }}-cargo-release
- run: cargo install cargo-release
- if: steps.cargo_release_cache.outputs.cache-hit != 'true'
+ if: steps.cargo_release_cache_restore.outputs.cache-hit != 'true'
+
+ - name: cargo-release cache save
+ id: cargo_release_cache_save
+ uses: actions/cache/save@v4
+ if: always() && steps.cargo_release_cache_restore.outputs.cache-hit != 'true'
+ with:
+ path: ~/.cargo/bin/cargo-release
+ key: ${{ runner.os }}-cargo-release
- name: cargo login
run: cargo login ${{ secrets.CRATES_IO_API_TOKEN }}
# allow-branch HEAD is because GitHub actions switches
# to the tag while building, which is a detached head
-
- # Publishing is currently messy, because:
- #
- # * `peace_rt_model_core` exports `NativeError` or `WebError` depending on the target.
- # * `peace_rt_model_web` fails to build when publishing the workspace for a native target.
- # * `peace_rt_model_web` still needs its dependencies to be published before it can be
- # published.
- # * `peace_rt_model_hack` needs `peace_rt_model_web` to be published before it can be
- # published.
- #
- # We *could* pass through `--no-verify` so `cargo` doesn't build the crate before publishing,
- # which is reasonable, since this job only runs after the Linux, Windows, and WASM builds
- # have passed.
- name: "cargo release publish"
run: |-
cargo release \
From 0c8d9f5d4c7d2c2d95055df2717d21f73810be96 Mon Sep 17 00:00:00 2001
From: Azriel Hoh
Date: Sat, 12 Apr 2025 13:32:42 +1200
Subject: [PATCH 02/17] Update dependency versions.
---
Cargo.toml | 40 ++++++++++++++++++++++------------------
crate/model/Cargo.toml | 1 +
2 files changed, 23 insertions(+), 18 deletions(-)
diff --git a/Cargo.toml b/Cargo.toml
index eccf3ee..5af4127 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -61,38 +61,42 @@ dot_ix_static_check_macros = { version = "0.9.2", path = "crate/static_check_mac
dot_ix_web_components = { version = "0.9.2", path = "crate/web_components" }
# external crates
-axum = "0.7.9"
+axum = "0.8.3"
cfg-if = "1"
console_error_panic_hook = "0.1"
console_log = "1"
gloo-net = "0.6.0"
-indexmap = "2.7.1"
-indoc = "2.0.5"
+id_newtype = "0.1.0"
+indexmap = "2.9.0"
+indoc = "2.0.6"
js-sys = "0.3.77"
web-sys = "0.3.77"
-leptos = { version = "0.7.4" }
-leptos_axum = "0.7.4"
-leptos_meta = { version = "0.7.4" }
-leptos_router = { version = "0.7.4" }
-leptos_router_macro = { version = "0.7.4" }
-leptos-use = "0.15.5"
+leptos = { version = "0.8.0-rc1" }
+leptos_axum = "0.8.0-rc1"
+leptos_meta = { version = "0.8.0-rc1" }
+leptos_router = { version = "0.8.0-rc1" }
+leptos_router_macro = { version = "0.8.0-rc1" }
+leptos-use = "0.16.0-beta"
log = "0.4"
log4rs = { version = "1.3.0", default-features = false }
monaco = "0.5.0"
-serde = "1.0.217"
-tempfile = "3.15.0"
-tokio = "1.43.0"
+serde = "1.0.219"
+tempfile = "3.19.1"
+tokio = "1.44.2"
tower = "0.5.2"
wasm-bindgen = "0.2.100"
tailwind-css = "0.13.0"
-thiserror = "2.0.11"
+thiserror = "2.0.12"
tracing = "0.1.41"
-http = "1.2.0"
-proc-macro2 = "1.0.93"
-quote = "1.0.38"
-reqwest = "0.12.12"
-syn = "2.0.96"
+http = "1.3.1"
+proc-macro2 = "1.0.95"
+quote = "1.0.40"
+reqwest = "0.12.15"
+syn = "2.0.100"
serde_yaml = "0.9.34"
[workspace.lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(coverage_nightly)'] }
+
+[patch.crates-io]
+leptos-use = { git = "https://github.com/sabify/leptos-use.git", branch = "leptos-v0.8.0-rc1" }
diff --git a/crate/model/Cargo.toml b/crate/model/Cargo.toml
index 89c7729..74fd612 100644
--- a/crate/model/Cargo.toml
+++ b/crate/model/Cargo.toml
@@ -17,6 +17,7 @@ doctest = false
test = false
[dependencies]
+id_newtype = { workspace = true }
indexmap = { workspace = true, features = ["serde"] }
serde = { workspace = true, features = ["derive"] }
dot_ix_static_check_macros = { workspace = true }
From aebca95c8d0b18a209fba5a8c434d86c6e667090 Mon Sep 17 00:00:00 2001
From: Azriel Hoh
Date: Sat, 12 Apr 2025 13:32:59 +1200
Subject: [PATCH 03/17] Use `id_newtype` crate to define ID newtypes.
---
crate/model/src/common.rs | 2 -
crate/model/src/common/any_id.rs | 2 +-
crate/model/src/common/edge_id.rs | 2 +-
crate/model/src/common/id_newtype.rs | 186 ---------------------------
crate/model/src/common/image_id.rs | 2 +-
crate/model/src/common/node_id.rs | 2 +-
crate/model/src/common/tag_id.rs | 2 +-
crate/model/src/lib.rs | 3 +
8 files changed, 8 insertions(+), 193 deletions(-)
delete mode 100644 crate/model/src/common/id_newtype.rs
diff --git a/crate/model/src/common.rs b/crate/model/src/common.rs
index 5323eb1..14d0d77 100644
--- a/crate/model/src/common.rs
+++ b/crate/model/src/common.rs
@@ -1,4 +1,3 @@
-pub(crate) use self::id_newtype::id_newtype;
pub use self::{
any_id::{AnyId, AnyIdInvalidFmt},
dot_src_and_styles::DotSrcAndStyles,
@@ -34,7 +33,6 @@ mod edge_descs;
mod edge_id;
mod edge_tags_set;
mod edges;
-mod id_newtype;
mod image_id;
mod images;
mod node_descs;
diff --git a/crate/model/src/common/any_id.rs b/crate/model/src/common/any_id.rs
index 630625d..6217df9 100644
--- a/crate/model/src/common/any_id.rs
+++ b/crate/model/src/common/any_id.rs
@@ -12,7 +12,7 @@ use crate::common::{EdgeId, NodeId, TagId};
#[derive(Clone, Debug, Hash, PartialEq, Eq, Deserialize, Serialize)]
pub struct AnyId(Cow<'static, str>);
-crate::common::id_newtype!(AnyId, AnyIdInvalidFmt, node_id);
+id_newtype::id_newtype!(AnyId, AnyIdInvalidFmt, node_id);
impl From for AnyId {
fn from(node_id: NodeId) -> Self {
diff --git a/crate/model/src/common/edge_id.rs b/crate/model/src/common/edge_id.rs
index 096252f..f1a3146 100644
--- a/crate/model/src/common/edge_id.rs
+++ b/crate/model/src/common/edge_id.rs
@@ -23,7 +23,7 @@ use crate::common::AnyId;
#[derive(Clone, Debug, Hash, PartialEq, Eq, Deserialize, Serialize)]
pub struct EdgeId(Cow<'static, str>);
-crate::common::id_newtype!(EdgeId, EdgeIdInvalidFmt, edge_id);
+id_newtype::id_newtype!(EdgeId, EdgeIdInvalidFmt, edge_id);
impl From for EdgeId {
fn from(any_id: AnyId) -> Self {
diff --git a/crate/model/src/common/id_newtype.rs b/crate/model/src/common/id_newtype.rs
deleted file mode 100644
index c18c27d..0000000
--- a/crate/model/src/common/id_newtype.rs
+++ /dev/null
@@ -1,186 +0,0 @@
-/// Implements common behaviour for an ID type.
-///
-/// The implemented behaviour includes:
-///
-/// * `IdType::new`
-/// * `IdType::new_unchecked`
-/// * `IdType::is_valid_id`
-/// * `IdType::into_inner`
-/// * `std::ops::Deref`
-/// * `std::ops::DerefMut`
-/// * `std::fmt::Display`
-/// * `std::str::FromStr`
-/// * `TryFrom`
-/// * `TryFrom<&'static str>`
-///
-/// A separate error type is also generated, which indicates an invalid value
-/// when the ID type is instantiated with `new`.
-///
-/// # Usage
-///
-/// ```rust
-/// use std::borrow::Cow;
-///
-/// // replace this with your ID type's macro
-/// use dot_ix_static_check_macros::my_id_type;
-/// use serde::{Deserialize, Serialize};
-///
-/// // Rename your ID type
-/// #[derive(Clone, Debug, Hash, PartialEq, Eq, Deserialize, Serialize)]
-/// pub struct MyIdType(Cow<'static, str>);
-///
-/// crate::id_newtype!(
-/// MyIdType, // Name of the ID type
-/// MyIdTypeInvalidFmt, // Name of the invalid value error
-/// my_id_type, // Name of the static check macro
-/// );
-/// ```
-macro_rules! id_newtype {
- ($ty_name:ident, $ty_err_name:ident, $macro_name:ident) => {
- impl $ty_name {
- #[doc = concat!("Returns a new `", stringify!($ty_name), "` if the given `&str` is valid.")]
- ///
- #[doc = concat!("Most users should use the [`", stringify!($macro_name), "!`] macro as this provides")]
- /// compile time checks and returns a `const` value.
- ///
- #[doc = concat!("[`", stringify!($macro_name), "!`]: dot_ix_static_check_macros::profile")]
- pub fn new(s: &'static str) -> Result> {
- Self::try_from(s)
- }
-
- #[doc = concat!("Returns a new `", stringify!($ty_name), "`.")]
- ///
- #[doc = concat!("Most users should use the [`", stringify!($macro_name), "!`] macro as this provides")]
- /// compile time checks and returns a `const` value.
- ///
- #[doc = concat!("[`", stringify!($macro_name), "!`]: dot_ix_static_check_macros::profile")]
- #[doc(hidden)]
- pub const fn new_unchecked(s: &'static str) -> Self {
- Self(std::borrow::Cow::Borrowed(s))
- }
-
- /// Returns whether the provided `&str` is a valid station identifier.
- pub fn is_valid_id(proposed_id: &str) -> bool {
- let mut chars = proposed_id.chars();
- let first_char = chars.next();
- let first_char_valid = first_char
- .map(|c| c.is_ascii_alphabetic() || c == '_')
- .unwrap_or(false);
- let remainder_chars_valid =
- chars.all(|c| c.is_ascii_alphabetic() || c == '_' || c.is_ascii_digit());
-
- first_char_valid && remainder_chars_valid
- }
-
- /// Returns the inner `Cow<'static, str>`.
- pub fn into_inner(self) -> Cow<'static, str> {
- self.0
- }
-
- /// Returns the `&str` held by this ID.
- pub fn as_str(&self) -> &str {
- &self.0
- }
- }
-
- impl std::ops::Deref for $ty_name {
- type Target = std::borrow::Cow<'static, str>;
-
- fn deref(&self) -> &Self::Target {
- &self.0
- }
- }
-
- impl std::fmt::Display for $ty_name {
- fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
- write!(f, "{}", self.0)
- }
- }
-
- impl TryFrom for $ty_name {
- type Error = $ty_err_name<'static>;
-
- fn try_from(s: String) -> Result<$ty_name, $ty_err_name<'static>> {
- if Self::is_valid_id(&s) {
- Ok($ty_name(std::borrow::Cow::Owned(s)))
- } else {
- let s = std::borrow::Cow::Owned(s);
- Err($ty_err_name::new(s))
- }
- }
- }
-
- impl TryFrom<&'static str> for $ty_name {
- type Error = $ty_err_name<'static>;
-
- fn try_from(s: &'static str) -> Result<$ty_name, $ty_err_name<'static>> {
- if Self::is_valid_id(s) {
- Ok($ty_name(std::borrow::Cow::Borrowed(s)))
- } else {
- let s = std::borrow::Cow::Borrowed(s);
- Err($ty_err_name::new(s))
- }
- }
- }
-
- impl std::str::FromStr for $ty_name {
- type Err = $ty_err_name<'static>;
-
- fn from_str(s: &str) -> Result<$ty_name, $ty_err_name<'static>> {
- if Self::is_valid_id(s) {
- Ok($ty_name(std::borrow::Cow::Owned(String::from(s))))
- } else {
- let s = std::borrow::Cow::Owned(String::from(s));
- Err($ty_err_name::new(s))
- }
- }
- }
-
- impl std::borrow::Borrow for $ty_name {
- fn borrow(&self) -> &str {
- &self.0
- }
- }
-
- impl<'s> std::borrow::Borrow for &'s $ty_name {
- fn borrow(&self) -> &str {
- &self.0
- }
- }
-
- #[doc = concat!("Error indicating `", stringify!($ty_name), "` provided is not in the correct format.")]
- #[derive(Debug, PartialEq, Eq)]
- pub struct $ty_err_name<'s> {
- /// String that was provided for the `$ty_name`.
- value: std::borrow::Cow<'s, str>,
- }
-
- impl<'s> $ty_err_name<'s> {
- #[doc = concat!("Returns a new `", stringify!($ty_err_name), "` error.")]
- pub fn new(value: std::borrow::Cow<'s, str>) -> Self {
- Self { value }
- }
-
- #[doc = concat!("Returns the value that failed to be parsed as a [`", stringify!($ty_name), "`].")]
- pub fn value(&self) -> &std::borrow::Cow<'s, str> {
- &self.value
- }
- }
-
- impl<'s> std::fmt::Display for $ty_err_name<'s> {
- fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
- write!(
- f,
- "`{value}` is not a valid `{ty_name}`.\n\
- `{ty_name}`s must begin with a letter or underscore, and contain only letters, numbers, or underscores.",
- ty_name = stringify!($ty_name),
- value = self.value
- )
- }
- }
-
- impl<'s> std::error::Error for $ty_err_name<'s> {}
- };
-}
-
-pub(crate) use id_newtype;
diff --git a/crate/model/src/common/image_id.rs b/crate/model/src/common/image_id.rs
index a6f209f..167e55c 100644
--- a/crate/model/src/common/image_id.rs
+++ b/crate/model/src/common/image_id.rs
@@ -23,7 +23,7 @@ use crate::common::AnyId;
#[derive(Clone, Debug, Hash, PartialEq, Eq, Deserialize, Serialize)]
pub struct ImageId(Cow<'static, str>);
-crate::common::id_newtype!(ImageId, ImageIdInvalidFmt, image_id);
+id_newtype::id_newtype!(ImageId, ImageIdInvalidFmt, image_id);
impl From for ImageId {
fn from(any_id: AnyId) -> Self {
diff --git a/crate/model/src/common/node_id.rs b/crate/model/src/common/node_id.rs
index 7ef0c57..2e10ed4 100644
--- a/crate/model/src/common/node_id.rs
+++ b/crate/model/src/common/node_id.rs
@@ -23,7 +23,7 @@ use crate::common::AnyId;
#[derive(Clone, Debug, Hash, PartialEq, Eq, Deserialize, Serialize)]
pub struct NodeId(Cow<'static, str>);
-crate::common::id_newtype!(NodeId, NodeIdInvalidFmt, node_id);
+id_newtype::id_newtype!(NodeId, NodeIdInvalidFmt, node_id);
impl From for NodeId {
fn from(any_id: AnyId) -> Self {
diff --git a/crate/model/src/common/tag_id.rs b/crate/model/src/common/tag_id.rs
index 55df28e..4929f94 100644
--- a/crate/model/src/common/tag_id.rs
+++ b/crate/model/src/common/tag_id.rs
@@ -23,7 +23,7 @@ use crate::common::AnyId;
#[derive(Clone, Debug, Hash, PartialEq, Eq, Deserialize, Serialize)]
pub struct TagId(Cow<'static, str>);
-crate::common::id_newtype!(TagId, TagIdInvalidFmt, tag_id);
+id_newtype::id_newtype!(TagId, TagIdInvalidFmt, tag_id);
impl From for TagId {
fn from(any_id: AnyId) -> Self {
diff --git a/crate/model/src/lib.rs b/crate/model/src/lib.rs
index 9ac577a..b362f24 100644
--- a/crate/model/src/lib.rs
+++ b/crate/model/src/lib.rs
@@ -129,6 +129,9 @@
//! - tag_2: "Tag 2"
//! ```
+#[macro_use]
+extern crate id_newtype;
+
// Re-exports
pub use dot_ix_static_check_macros::{edge_id, node_id, tag_id};
pub use indexmap::IndexMap;
From ebec4ea76bb5185d305ffb81e12ecbaa8f0de85a Mon Sep 17 00:00:00 2001
From: Azriel Hoh
Date: Sat, 12 Apr 2025 20:47:15 +1200
Subject: [PATCH 04/17] Remove `"server_side_graphviz"` feature.
---
.github/workflows/ci.yml | 8 +-
Cargo.toml | 15 +-
README.md | 16 --
crate/web_components/Cargo.toml | 7 -
crate/web_components/src/dot_svg.rs | 248 ++--------------------------
deny.toml | 2 +-
playground/Cargo.toml | 1 -
7 files changed, 20 insertions(+), 277 deletions(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index bb2f03d..0c7a456 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -42,7 +42,7 @@ jobs:
run: cargo install --locked cargo-about
- name: cargo-about generate licenses
- run: cargo about generate --workspace --features "server_side_graphviz" about.hbs > doc/src/licenses.html
+ run: cargo about generate --workspace about.hbs > doc/src/licenses.html
fmt:
name: Rustfmt
@@ -91,7 +91,7 @@ jobs:
- name: 'Run clippy (server side graphviz)'
# we cannot use `--all-features` because `dot_ix` has features that are mutually exclusive.
run: |
- cargo clippy --workspace --features "server_side_graphviz" -- -D warnings
+ cargo clippy --workspace -- -D warnings
coverage:
name: Coverage
@@ -164,7 +164,7 @@ jobs:
- name: 'Build playground (server side graphviz)'
working-directory: ./playground
- run: cargo leptos build --features "server_side_graphviz" -v
+ run: cargo leptos build --features -v
build_and_test_windows:
name: Build and Test (Windows)
@@ -214,4 +214,4 @@ jobs:
- name: 'Build playground (server side graphviz)'
working-directory: ./playground
- run: cargo leptos build --features "server_side_graphviz" -v
+ run: cargo leptos build -v
diff --git a/Cargo.toml b/Cargo.toml
index 5af4127..67ae099 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -24,22 +24,14 @@ dot_ix_rt = { workspace = true, optional = true }
dot_ix_web_components = { workspace = true, optional = true }
[features]
-default = [
- "rt",
- "web_components",
-]
+default = ["rt", "web_components"]
rt = ["dep:dot_ix_rt"]
web_components = ["dep:dot_ix_web_components"]
ssr = ["dot_ix_web_components?/ssr"]
-server_side_graphviz = ["dot_ix_web_components?/server_side_graphviz"]
[workspace]
-members = [
- "crate/*",
- "playground",
- "workspace_tests",
-]
+members = ["crate/*", "playground", "workspace_tests"]
[workspace.package]
version = "0.9.2"
@@ -97,6 +89,3 @@ serde_yaml = "0.9.34"
[workspace.lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(coverage_nightly)'] }
-
-[patch.crates-io]
-leptos-use = { git = "https://github.com/sabify/leptos-use.git", branch = "leptos-v0.8.0-rc1" }
diff --git a/README.md b/README.md
index b683ed1..1f8a4ce 100644
--- a/README.md
+++ b/README.md
@@ -31,10 +31,6 @@ dot_ix = "0.9.2"
# Enables the `FlexDiag` web component.
dot_ix = { version = "0.9.2", features = ["flex_diag"] }
-
-# Enables server side dot generation.
-# Requires graphviz `dot` to be installed server side.
-dot_ix = { version = "0.9.2", features = ["server_side_graphviz"] }
```
@@ -46,20 +42,8 @@ cargo install cargo-leptos
# Then, one of:
# * client side rendering -- uses WASM compiled graphviz to generate the graph.
cargo leptos watch
-# * server side rendering -- runs `dot` on the server to generate the graph.
-# Requires `graphviz` to be installed.
-cargo leptos watch --features "server_side_graphviz" -v
```
-For server side rendering, the `"server_side_graphviz"` feature needs to be passed in separately because that feature still needs to be enabled for the lib compilation, i.e.
-
-* server side rendering:
- - lib features: `"server_side_graphviz"`
- - bin features: `"ssr,server_side_graphviz"`
-* client side rendering:
- - lib features: `""`
- - bin features: `""`
-
## To Do
diff --git a/crate/web_components/Cargo.toml b/crate/web_components/Cargo.toml
index 02d4c79..733714e 100644
--- a/crate/web_components/Cargo.toml
+++ b/crate/web_components/Cargo.toml
@@ -24,14 +24,11 @@ http = { workspace = true }
leptos = { workspace = true }
leptos_axum = { workspace = true, optional = true }
leptos_meta = { workspace = true }
-serde = { workspace = true, optional = true, features = ["derive"] }
tempfile = { workspace = true, optional = true }
-tokio = { workspace = true, optional = true }
thiserror = { workspace = true }
[target.'cfg(target_arch = "wasm32")'.dependencies]
js-sys = { workspace = true }
-serde = { workspace = true, optional = true, features = ["derive"] }
serde-wasm-bindgen = { version = "0.6.5" }
wasm-bindgen = { workspace = true }
web-sys = { workspace = true, features = ["Document", "Element", "HtmlElement", "Url", "UrlSearchParams", "Window"] }
@@ -44,7 +41,3 @@ ssr = [
"leptos/ssr",
"leptos_meta/ssr",
]
-server_side_graphviz = [
- "dep:serde",
- "dep:tokio",
-]
diff --git a/crate/web_components/src/dot_svg.rs b/crate/web_components/src/dot_svg.rs
index fee8b17..3a3e1b1 100644
--- a/crate/web_components/src/dot_svg.rs
+++ b/crate/web_components/src/dot_svg.rs
@@ -1,36 +1,18 @@
+use dot_ix_model::{common::DotSrcAndStyles, info_graph::InfoGraph};
use leptos::{
component,
- prelude::{ClassAttribute, ElementChild, Get, Signal},
+ html::Div,
+ prelude::{
+ ClassAttribute, Effect, ElementChild, Get, GlobalAttributes, GlobalOnAttributes, NodeRef,
+ NodeRefAttribute, Signal,
+ },
view, IntoView,
};
+use leptos_meta::Script;
-#[cfg(not(feature = "server_side_graphviz"))]
-use leptos::prelude::{Effect, NodeRef};
-
-use dot_ix_model::{common::DotSrcAndStyles, info_graph::InfoGraph};
-
-#[cfg(feature = "server_side_graphviz")]
-use leptos::{
- prelude::{InnerHtmlAttribute, Resource, ServerFnError},
- server,
- server_fn::error::NoCustomError,
- suspense::Suspense,
-};
-
-#[cfg(any(
- all(feature = "ssr", feature = "server_side_graphviz"),
- target_arch = "wasm32"
-))]
+#[cfg(target_arch = "wasm32")]
use dot_ix_model::common::{dot_src_and_styles::GraphvizImage, Images};
-#[cfg(not(feature = "server_side_graphviz"))]
-use leptos::prelude::{GlobalAttributes, GlobalOnAttributes, NodeRefAttribute};
-
-#[cfg(not(feature = "server_side_graphviz"))]
-use leptos::html::Div;
-#[cfg(not(feature = "server_side_graphviz"))]
-use leptos_meta::Script;
-
cfg_if::cfg_if! { if #[cfg(target_arch = "wasm32")] {
use wasm_bindgen::{prelude::wasm_bindgen, JsValue};
@@ -41,74 +23,14 @@ cfg_if::cfg_if! { if #[cfg(target_arch = "wasm32")] {
}
}}
-#[cfg(not(feature = "server_side_graphviz"))]
const SVG_WRITE_TO_CLIPBOARD: &str = include_str!("dot_svg/svg_write_to_clipboard.js");
-#[cfg(feature = "server_side_graphviz")]
-#[server]
-pub async fn dot_svg(
- info_graph: InfoGraph,
- dot_src_and_styles: DotSrcAndStyles,
-) -> Result<(String, String), ServerFnError> {
- use std::process::Stdio;
- use tokio::io::{AsyncReadExt, AsyncWriteExt};
-
- let DotSrcAndStyles {
- dot_src,
- styles: _,
- opts: _,
- theme_warnings: _,
- } = dot_src_and_styles;
-
- let mut dot_process = tokio::process::Command::new("dot")
- .arg("-Tsvg")
- .stdin(Stdio::piped())
- .stdout(Stdio::piped())
- .stderr(Stdio::piped())
- .spawn()
- .expect("Failed to spawn dot command");
-
- if let Some(mut stdin) = dot_process.stdin.take() {
- stdin
- .write_all(dot_src.as_bytes())
- .await
- .map_err(|error| ServerFnError::::ServerError(format!("{error}")))?;
- }
-
- let mut dot_svg = String::with_capacity(dot_src.len());
- if let Some(mut stdout) = dot_process.stdout.take() {
- stdout
- .read_to_string(&mut dot_svg)
- .await
- .map_err(|error| ServerFnError::::ServerError(format!("{error}")))?;
- }
-
- let mut dot_stderr = String::new();
- if let Some(mut stderr) = dot_process.stderr.take() {
- stderr
- .read_to_string(&mut dot_stderr)
- .await
- .map_err(|error| ServerFnError::::ServerError(format!("{error}")))?;
- }
-
- dot_process.wait().await.map_err(|error| {
- ServerFnError::::ServerError(format!("{dot_stderr}{error}"))
- })?;
-
- let styles = dot_svg_styles(&dot_src).await?;
-
- let images = info_graph.images();
- let image_defs = svg_image_defs(images);
- dot_svg = dot_svg_sanitize(&dot_svg, &styles, images, &image_defs);
- dot_svg = dot_svg_append_extra(&dot_svg, info_graph.svg_extra());
-
- Ok((dot_svg, dot_stderr))
+#[cfg(target_arch = "wasm32")]
+fn dot_svg_append_extra(dot_svg: &str, svg_extra: &str) -> String {
+ dot_svg.replacen(" String {
images
.iter()
@@ -138,10 +60,7 @@ fn svg_image_defs(images: &Images) -> String {
/// * `dot_svg`: The SVG generated by `dot`.
/// * `styles`: The CSS styles to include within the ``
/// element.
-#[cfg(any(
- all(feature = "ssr", feature = "server_side_graphviz"),
- target_arch = "wasm32"
-))]
+#[cfg(target_arch = "wasm32")]
fn dot_svg_sanitize(dot_svg: &str, styles: &str, images: &Images, images_defs: &str) -> String {
let dot_svg = dot_svg
.replacen("{styles}\n String {
- dot_svg.replacen(" Result> {
- use std::process::Stdio;
- use tokio::io::AsyncReadExt;
-
- let tempdir = tempfile::tempdir()
- .map_err(|error| ServerFnError::::ServerError(format!("{error}")))?;
-
- let dot_path = tempdir.path().join("dot.dot");
- let dot_write = tokio::fs::write(&dot_path, dot_src);
-
- let tailwind_config_path = tempdir.path().join("tailwind.config.js");
- let tailwind_config_write = tokio::fs::write(
- &tailwind_config_path,
- b"/** @type {import('tailwindcss').Config} */\nmodule.exports = { content: ['./dot.dot'] }",
- );
-
- let tailwind_css_path = tempdir.path().join("tailwind.css");
- let tailwind_css_write = tokio::fs::write(
- &tailwind_css_path,
- b"\n@tailwind components;\n@tailwind utilities;\n",
- );
-
- let ((), (), ()) = tokio::try_join!(tailwind_config_write, dot_write, tailwind_css_write,)
- .map_err(|error| ServerFnError::::ServerError(format!("{error}")))?;
-
- let mut tailwind_process = tokio::process::Command::new("tailwind")
- .current_dir(tempdir.path())
- .arg("-i")
- .arg(&tailwind_css_path)
- .stdin(Stdio::piped())
- .stdout(Stdio::piped())
- .stderr(Stdio::piped())
- .spawn()
- .map_err(|error| ServerFnError::::ServerError(format!("{error}")))?;
-
- let mut svg_styles = String::with_capacity(dot_src.len());
- if let Some(mut stdout) = tailwind_process.stdout.take() {
- stdout
- .read_to_string(&mut svg_styles)
- .await
- .map_err(|error| ServerFnError::::ServerError(format!("{error}")))?;
- }
-
- let mut tailwind_stderr = String::new();
- if let Some(mut stderr) = tailwind_process.stderr.take() {
- stderr
- .read_to_string(&mut tailwind_stderr)
- .await
- .map_err(|error| ServerFnError::::ServerError(format!("{error}")))?;
- }
-
- tailwind_process.wait().await.map_err(|error| {
- ServerFnError::::ServerError(format!("{tailwind_stderr}{error}"))
- })?;
-
- Ok(svg_styles)
-}
-
-/// Renders a graphviz graph as an SVG.
-#[cfg(feature = "server_side_graphviz")]
-#[component]
-pub fn DotSvg(
- info_graph: Signal,
- dot_src_and_styles: Signal
}
- >
- { move || {
- dot_svg_and_error_resource.get()
- .map(|(dot_svg, error_text)| {
- let error_text_empty = error_text.is_empty();
- view! {
-
- }
- })
- }}
-
- }
-}
-
/// Renders a graphviz graph as an SVG.
///
/// TODO: Use `postcss` to generate styles on the client side via function.
@@ -338,7 +117,6 @@ pub fn DotSvg(
///
/// const css = generateTailwindCss('HTML content
')
/// ```
-#[cfg(not(feature = "server_side_graphviz"))]
#[component]
pub fn DotSvg(
info_graph: Signal,
diff --git a/deny.toml b/deny.toml
index 8b38dad..5dcfd36 100644
--- a/deny.toml
+++ b/deny.toml
@@ -46,7 +46,7 @@ all-features = true
no-default-features = false
# If set, these feature will be enabled when collecting metadata. If `--features`
# is specified on the cmd line they will take precedence over this option.
-features = ["server_side_graphviz"]
+features = []
[output]
# When outputting inclusion graphs in diagnostics that include features, this
diff --git a/playground/Cargo.toml b/playground/Cargo.toml
index 45ae046..44a5719 100644
--- a/playground/Cargo.toml
+++ b/playground/Cargo.toml
@@ -69,7 +69,6 @@ ssr = [
csr = [
"leptos/csr",
]
-server_side_graphviz = ["dot_ix/server_side_graphviz"]
[package.metadata.cargo-all-features]
denylist = ["axum", "tokio", "tower", "tower-http", "leptos_axum"]
From 313deed708ba390cee37f6e17a475c264db5efc3 Mon Sep 17 00:00:00 2001
From: Azriel Hoh
Date: Sun, 13 Apr 2025 14:49:02 +1200
Subject: [PATCH 05/17] Remove `tailwind.config.js` as Tailwind 4 and
`cargo-leptos 0.2.29+` don't need it.
---
playground/Cargo.toml | 2 +-
playground/style/tailwind.config.js | 11 -----------
2 files changed, 1 insertion(+), 12 deletions(-)
delete mode 100644 playground/style/tailwind.config.js
diff --git a/playground/Cargo.toml b/playground/Cargo.toml
index 44a5719..c2e8103 100644
--- a/playground/Cargo.toml
+++ b/playground/Cargo.toml
@@ -88,7 +88,7 @@ site-pkg-dir = "pkg"
# [Optional] The source CSS file. If it ends with .sass or .scss then it will be compiled by dart-sass into CSS. The CSS is optimized by Lightning CSS before being written to //app.css
# style-file = "style/main.scss"
tailwind-input-file = "style/tailwind.css"
-tailwind-config-file = "style/tailwind.config.js"
+# tailwind-config-file = "style/tailwind.config.js"
# Assets source dir. All files found here will be copied and synchronized to site-root.
# The assets-dir cannot have a sub directory with the same name/path as site-pkg-dir.
#
diff --git a/playground/style/tailwind.config.js b/playground/style/tailwind.config.js
deleted file mode 100644
index a7a6f2b..0000000
--- a/playground/style/tailwind.config.js
+++ /dev/null
@@ -1,11 +0,0 @@
-/** @type {import('tailwindcss').Config} */
-module.exports = {
- content: [
- // Relative to workspace root / where you run `cargo leptos` from.
- '**/src/**/*.rs',
- ],
- theme: {
- extend: {},
- },
- plugins: [],
-}
From 317ca0aee618a5b69738b37c508390011d3910ad Mon Sep 17 00:00:00 2001
From: Azriel Hoh
Date: Sun, 13 Apr 2025 14:49:45 +1200
Subject: [PATCH 06/17] Remove `Trunk.toml` as `trunk` can copy assets without
needing `cargo-leptos`.
---
playground/Trunk.toml | 6 ------
playground/index.html | 9 ++++-----
2 files changed, 4 insertions(+), 11 deletions(-)
delete mode 100644 playground/Trunk.toml
diff --git a/playground/Trunk.toml b/playground/Trunk.toml
deleted file mode 100644
index c790f43..0000000
--- a/playground/Trunk.toml
+++ /dev/null
@@ -1,6 +0,0 @@
-[[hooks]]
-stage = "pre_build"
-command = "cargo"
-command_arguments = ["leptos", "build", "-v"]
-# command = "sh"
-# command_arguments = ["-c", "npx tailwindcss -c style/tailwind.config.js -i style/tailwind.css -o target/site/pkg/dot_ix.css"]
diff --git a/playground/index.html b/playground/index.html
index 9b2f066..7b0f67a 100644
--- a/playground/index.html
+++ b/playground/index.html
@@ -13,11 +13,10 @@
Would be good if we can just specify `target/site`,
and `trunk` copies the contents of the `site` directory.
-->
-
-
-
-
-
+
+
+
+