grok-build-upstream-mirror/third_party/mermaid-to-svg/Cargo.toml
grokkybara[bot] c68e39f604 Publish harness and TUI open-source
initial sync from the monorepo
2026-07-16 06:46:02 +01:00

162 lines
10 KiB
TOML

# Vendored third-party crate.
#
# Upstream: warpdotdev/mermaid-to-svg (MIT) —
# https://github.com/warpdotdev/mermaid-to-svg
# rev 40cecf2be376e47e15053eadbfb782a531777420
#
# Why vendored (not a crates.io pin): the engine renders untrusted model output
# and is a young dependency. Vendoring gives a full audit surface and immunity to
# upstream yanks for the hardened CLI binary. Warp's engine delegates layout
# to a Rust port of dagre.js (the same algorithm mermaid.js uses), which fixes
# the cyclic-flowchart back-edge mis-routing of the previous engine. See
# crates/codegen/xai-grok-mermaid.
#
# ============================================================================
# VENDORING NOTES — single source of truth. Re-apply / re-bless ALL of the
# following on every upstream upgrade:
# ============================================================================
#
# Local modifications to the upstream source:
# 1. NOT VENDORED: `src/bin/render_mermaid.rs` (CLI binary). Its `[[bin]]` and
# the dev-only deps (insta/rust-embed/resvg/roxmltree/image/anyhow/serde*)
# are dropped — `xai-grok-mermaid` rasterizes the SVG itself with the
# workspace `resvg`, so this is used as an SVG generator only.
# 2. NOT VENDORED: every `*_tests.rs` snapshot/fixture test plus `reference_svg`
# and `fixtures` (they `include`/embed un-vendored `samples/` assets and need
# the dropped dev-deps). Their `#[cfg(test)] #[path = "..."] mod tests;`
# declarations and the `pub mod fixtures;` / `mod reference_svg;` lines were
# removed from the kept sources. The two *in-source* `mod tests` blocks
# (`src/lib.rs` public-API smoke tests, `src/mermaid_port/dagre_layout_port.rs`
# unit tests) use no dev-deps and are kept; `[lib] doctest = false`. One
# LOCAL ADDITION to the kept `src/lib.rs` tests: `test_simple_c4_diagram`
# (marked in-source), filling the only dispatched diagram type that upstream
# left without a `test_simple_*` smoke test.
# 3. HERMETIC PATCH (src/mermaid_port/mod.rs): `is_enabled()` returns `false`
# unconditionally. Upstream read the `MERMAID_TO_SVG_USE_PORT` env var to
# enable an experimental flowchart layout "port"; reading the environment is
# non-deterministic over untrusted input, and the port mis-routes cyclic
# back-edges (detached arrowheads). The default `layout::compute_layout`
# path routes cycles correctly, so the port stays off. Because the port is
# unreachable, `mermaid_port::compute_layout_ported` carries an
# `#[allow(dead_code)]`; the module is kept verbatim (not deleted) so future
# re-vendor diffs stay minimal.
# 4. Dropped the unused `petgraph` and `regex` dependencies (declared upstream,
# referenced nowhere in the vendored source; `cargo shear` confirms).
# 5. `thiserror` pinned to "2" (upstream "1.0") to match the workspace; the
# `#[derive(Error)]` / `#[error("…")]` API used in `src/error.rs` is
# unchanged across the major.
# 6. `cargo fmt` (rustfmt) applied so the crate satisfies the workspace fmt
# gate; no semantic change.
# 7. LOCAL REWRITE (src/sequence_diagram.rs; deliberately NOT marked in-source
# — this note is the sole record, so re-apply it on every upstream
# upgrade): the upstream sequence parser hard-failed ("Unrecognized
# sequenceDiagram line") on most of the standard Mermaid sequence grammar. Added: `activate`/`deactivate`
# (+ the `+`/`-` message shorthand) drawn as lifeline activation bars;
# `actor`; `create`/`destroy`; `box … end`; `autonumber` (message-number
# prefixes); `title`; `accTitle`/`accDescr` (incl. `{ … }` blocks) and
# `links`/`link`/`properties` accepted-and-skipped; `par`/`and`,
# `critical`/`option`, `break`, `rect` fragments; the full arrow set
# (`->`, `-->`, `-x`, `--x`, `-)`, `--)`, `<<->>`, `<<-->>`) with per-type
# markers. Keyword matching is now case-insensitive and word-bounded
# (Mermaid's lexer is case-insensitive; `optimize…` is no longer an `opt`
# fragment). Arrow markers are theme-colored (were unstyled black,
# invisible-on-dark) and note text is fixed-dark on the fixed light-yellow
# note fill. Covered by the (likewise unmarked) `test_sequence_*` tests in
# src/lib.rs.
# 8. LOCAL MODIFICATION (new `unicode-width` dep): text width estimates count
# East Asian wide characters as two narrow units via `text_wrap::
# display_width_units` (upstream counted chars/graphemes, halving CJK label
# widths so they overflowed their nodes). Touches `text_wrap.rs` and the
# local estimators in `sequence_diagram.rs` / `xychart_diagram.rs` /
# `mindmap_diagram.rs`; ASCII measurement is unchanged. Covered by the
# `test_cjk_*` tests in src/lib.rs.
# 9. LOCAL MODIFICATION (src/parser.rs): support Mermaid's open edge-label
# syntax (`A -- text --> B`, `-- text ---`, `== text ==>`, `== text ===`,
# `-. text .-`; upstream only parsed the `|text|` form plus `-. text .->`),
# and make `find_edge_start` bracket/quote-aware so edge tokens inside node
# labels (`A["x --> y"]`) are not treated as edges. Upstream parsed
# `B -- 是 --> C` as a literal node named "B -- 是". Covered by the
# `test_open_edge_label_*` / `test_edge_tokens_inside_node_labels_*` tests
# in src/lib.rs.
# 10. LOCAL MODIFICATION (src/text_wrap.rs): a single unbreakable token (a
# "word" with no internal whitespace) is kept whole on its own line and the
# box widens to fit it, instead of being hard-sliced mid-identifier at a
# grapheme boundary once it exceeds `wrapping_width` (upstream sliced
# `mark_filter_restore_context` into `mark_filter_restore_conte` + `xt`).
# This matches Mermaid's default `htmlLabels: true` rendering, which this
# port does not implement (src/config.rs), so it is MORE faithful to
# upstream Mermaid. Because `wrap_text_lines` is the shared wrapper, this
# applies to ALL of its callers — flowchart node labels, edge labels, and
# subgraph titles, plus state-diagram node/edge labels (state diagrams parse
# into the same `FlowchartGraph` and reuse this layout/renderer) — not just
# node boxes. The class/er/requirement diagrams have their own renderers that
# call only `line_width` (single-line, no wrapping), so they are unaffected.
# Only a pathologically long token — wider than
# SINGLE_TOKEN_WIDTH_CAP_FACTOR (5x) the wrap width — is force-broken,
# preferring the last identifier boundary (`_`/`-`/`.`/`/`) under the cap.
# Per-diagram width is now intentionally bounded only by the downstream
# rasterizer's PNG caps (xai-grok-mermaid), not by the layout — a deliberate
# legibility-vs-completeness tradeoff. Multi-word labels still wrap at spaces
# as before (`wrapping_width` unchanged). Covered by the unit tests in
# `src/text_wrap.rs`.
# 11. LOCAL MODIFICATION (src/layout.rs): flowchart edges whose endpoint is a
# subgraph id (cluster-target edges) have the dagre route points that fall
# strictly inside the destination/source cluster rect trimmed (via
# `trim_cluster_interior_points`) before `clip_edge_to_boundaries`, so the
# edge approaches the cluster boundary from outside instead of routing to the
# first-declared interior member (`subgraph_entry_node_id`) and curling back.
# A single transition point is kept per trimmed side; the polyline never
# drops below two points. Only forward (non-back) cluster-target edges are
# affected — node-target edges and back edges are unchanged. Covered by the
# `trim_*` tests in src/layout.rs.
# 12. LOCAL REWRITE (src/xychart_diagram.rs): upstream only parsed a numeric
# x-axis (`x-axis min --> max`) + a single `line`, hard-failing on the
# categorical form `x-axis ["a", …]` (so such charts fell back to a code
# block — "opening image for this diagram fails"). Added: categorical
# (band-scale) x-axis; optional quoted axis titles (y rotated, x centered);
# quote stripping for the title/labels; multiple `line` series in distinct
# palette colors; y auto-ranging when no explicit range is given; and
# theme-colored axes/text (was a fixed near-black, invisible on dark). `bar`
# stays unsupported (ignored). Covered by `xychart_diagram::tests` here and
# the `categorical_xychart_*` raster test in
# crates/codegen/xai-grok-mermaid/tests/pure_engine.rs.
#
# Re-audit checklist:
# - This crate's own source contains no `unsafe` and no filesystem / network I/O.
# Text metrics are font-free (fixed char-width in `src/text_wrap.rs`), so the
# engine performs NO system-font enumeration or on-disk font cache — glyph
# rasterization is the separate, bundled-font `xai-grok-mermaid::rasterize`.
# - SIBLING VENDORED LAYOUT DEPS (this header is the audit source-of-truth for
# the whole stack): `ordered_hashmap` retains two `unsafe` raw-pointer blocks
# in `iter_mut`/`values_mut` (documented + re-audited in its own Cargo.toml);
# `dagre_rust` and `graphlib_rust` contain no `unsafe` (dagre's upstream
# `static mut` counter was replaced with an `AtomicUsize` — see its Cargo.toml).
# - YAML frontmatter parsing (`src/config.rs`, `src/kanban_diagram.rs`) uses the
# workspace `serde_yaml`; it parses in-memory source only (no file/URL refs).
[package]
name = "mermaid-to-svg"
version = "0.1.0"
edition = "2021"
description = "Convert Mermaid diagram source to SVG via a dagre layout port (vendored, library-only)"
license = "MIT"
repository = "https://github.com/warpdotdev/mermaid-to-svg"
publish = false
[lib]
name = "mermaid_to_svg"
path = "src/lib.rs"
doctest = false
[dependencies]
thiserror = "2"
dagre_rust = { path = "../dagre_rust" }
graphlib_rust = { path = "../graphlib_rust" }
unicode-segmentation = "1"
unicode-width = "0.2"
serde_yaml = "0.9"
# Clippy lints local/path crates (this vendored crate is one) under the
# workspace's `-D warnings`. We do not restyle upstream third-party code, so
# allow clippy here; our own crate (xai-grok-mermaid) is still fully linted.
[lints.clippy]
all = { level = "allow", priority = -1 }