Skip to content

Release 0.15.0: complete plotly.js 3.7 trace coverage, remove kaleido/EPS, dependency security bumps - #442

Open
jqnatividad wants to merge 17 commits into
plotly:mainfrom
dathere:release/0.15.0
Open

jqnatividad wants to merge 17 commits into
plotly:mainfrom
dathere:release/0.15.0

Conversation

@jqnatividad

@jqnatividad jqnatividad commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Release prep for plotly.rs 0.15.0, the last release on plotly.js 3.x. Per the discussion in #437, the plotly.js 4.x upgrade will be the basis for 0.16.0.

0.15.0 ships everything currently under [Unreleased] (plotly.js 3.0.1 → 3.7.0, the new trace types and the 3.7 attribute backfill), plus:

  • Complete trace-type coverage for plotly.js 3.7 (Tracking: trace types not yet exposed in plotly.rs (plotly.js 3.7.0 parity) #422): adds the last 13 trace types, so every non-deprecated plotly.js 3.7 trace type is exposed. With them come the ternary and Smith chart subplots.

  • Removes the deprecated Kaleido backend and ImageFormat::EPS, as announced for 0.15.0 in the 0.13.0 deprecation notices.

  • Security / dependencies: drops the unused zip build-dependency and bumps darling/syn, dirs and the examples' dependencies.

  • Versions: plotly 0.15.0, plotly_derive 0.15.0, plotly_static 0.2.0 (breaking: EPS removed; also carries the plotly.js 3.7.0 bundle).

⚠️ Publish order

plotly 0.15.0 depends on plotly_static = "0.2", and release.yml does not publish plotly_static (it goes through publish_plotly_static.yml). Publish in this order:

  1. plotly_static 0.2.0
  2. plotly_derive 0.15.0
  3. plotly 0.15.0

Changes

Kaleido / EPS removal (03a5dc4)

  • Removed plotly_kaleido from the workspace; removed the kaleido and kaleido_download features and the kaleido-gated Plot::{write_image, to_base64, to_svg} implementations.
  • Removed ImageFormat::EPS and the #![allow(deprecated)] in plotly_static that was waiting on 0.15.0.
  • Removed the kaleido example, and the kaleido/EPS sections from the README and book. Install snippets now point at 0.15, and the README WASM snippet's CDN link now points at plotly.js 3.7.0.

Dependencies (f1d5d06)

  • plotly_static: removed the zip build-dependency (build.rs never used it); dirs 6 → 7.
  • plotly_derive: darling 0.23 → 0.24 together with syn 2 → 3 (darling 0.24 is built on syn 3). No macro code changes needed.
  • examples: reqwest 0.13, env_logger 0.11, itertools 0.15, ndarray 0.17, rand/rand_chacha 0.10, with small API adaptations (RngExt::random, dropping the deprecated into_raw_vec).

Example fix (48b387b): the custom_controls sinusoidal slider built 52 traces (0..=num_steps) for 51 slider steps, so step 0 also showed a stray 5.1-frequency curve. It now builds 51.

Lints and an add_frames fix (a21da1f)

  • Fixes Plot::add_frames, which added every frame twice when the plot had no frames yet. Adds a regression test.

  • Theme statics in plotly::layout::themes (DEFAULT, PLOTLY_WHITE, …) are now std::sync::LazyLock<Template> instead of once_cell::sync::Lazy<Template>, and the once_cell dependency is dropped. This changes the type of public items. It only affects code that calls Lazy::force on them, and it lands in a release that is already breaking. It needs Rust 1.80+; no MSRV is declared.

  • Addresses clippy's pedantic missing_errors_doc, missing_panics_doc and doc_markdown, plus cargo::redundant_homepage:

    • adds # Errors/# Panics sections to public fallible APIs, including the wasm-only bindings and callbacks;
    • backticks identifiers in docs, and fixes an unbalanced-backtick comment that was copied across 8 traces;
    • removes the homepage fields that duplicated repository.

    A new clippy.toml treats WebDriver, MapLibre, GeoJSON, MathJax and ModeBar as product names rather than identifiers. CI doesn't enforce pedantic lints; this is cleanup.

Complete trace-type coverage (#422), one commit per group:

  • 7a4a297: BarPolar and FunnelArea. Adds LayoutPolar::bar_mode/bar_gap (PolarBarMode; plotly.js reads these per polar subplot), ThetaUnit::Gradians, and the funnelareacolorway/extendfunnelareacolors/hiddenlabels layout attributes.
  • 4479979: Cone, StreamTube, IsoSurface and Volume, sharing mesh3d::Lighting/LightPosition. Breaking: mesh3d::LightPosition x/y/z are now f64 instead of Vec<f64>. plotly.js expects one number per coordinate and silently ignored the arrays, so Mesh3D light positions never took effect.
  • 9abed12: Parcoords, with a numeric Dimension and ConstraintRange.
  • 00fde49: ScatterTernary and ScatterSmith, plus the new LayoutTernary/TernaryAxis and LayoutSmith/RealAxis/ImaginaryAxis subplots.
  • 7dec22b: Carpet (with CarpetAxis), ScatterCarpet and ContourCarpet.
  • 0f87192: CHANGELOG [0.15.0] entries for the above, a highlights summary, and the release date moved to 2026-10-18.
  • b7ab67c: fixes from the automated review of the commits above. label_alias on the new ternary, Smith and carpet axes is now a map, because plotly.js discards non-object values. Also corrects the StreamTube default-start docs, shows the grid_3d helper in the book, and fixes an unsupported text_info flag in the funnel area example.
  • 55555b2: Histogram2dContour. PlotType::Histogram2dContour existed, but no trace could emit it. Tracking: trace types not yet exposed in plotly.rs (plotly.js 3.7.0 parity) #422 had wrongly listed it as already exposed; the review of the CHANGELOG commit caught this.

Each commit includes examples and an mdBook recipe page for its traces. The book's index tables use text links rather than thumbnails for the new pages; PNG thumbnails can be added later.

Forward compatibility with 0.16.0: I checked every new struct, including nested sub-structs, key by key against both the plotly.js 3.7.0 and 4.1.2 plot-schema.json. All 13 traces exist in 4.1.2 with no new attributes. They deliberately omit the Chart Studio *src attributes, which plotly.js 4 removes, so they should carry over to the v4 upgrade unchanged.

Release (5d68616): version bumps and the CHANGELOG [0.15.0] section. Also removes the Funnel/Waterfall changelog entries that duplicated the #432 entry.

CI changes (please review)

  • build.yml: removed the kaleido entries from the matrices, lint steps and test excludes; the semver job now checks static_export_chromedriver instead of kaleido.
  • build.yml (16b30fb): dropped the pinned release-type: minor from the semver job. An explicit release type is applied verbatim, without the 0.y.z → major promotion, so the intentional removals would fail as major changes. Inferring from the version treats 0.14.1 → 0.15.0 as major, and during normal development (version unchanged) it still defaults to a minor-level check.
  • Deleted publish_plotly_kaleido.yml and the plotly_kaleido publish step in release.yml. The already-published plotly_kaleido crate on crates.io is unaffected.

Known issue: transitive zip 8.x

cargo audit still reports RUSTSEC-2026-0367/0368/0369 for zip 8.6.0. After this PR, zip comes only from webdriver-downloader 0.17 (zip ^8), a build-time dependency of plotly_static that fetches chromedriver/geckodriver.

  • All three advisories concern ZipArchive::extract() (symlinks and permissions). webdriver-downloader doesn't call extract(); it reads the driver entry with by_name + io::copy.
  • The fix is upstream in Change: bump zip to 9 ik1ne/webdriver-downloader#67 (zip 9; CI green, awaiting review). Once it's released, a 0.15.x patch can bump webdriver-downloader.
  • [patch.crates-io] wasn't used because it doesn't reach downstream users of the published crate.

The other advisories cargo audit reports against older lockfiles (rustls, quinn-proto, h2, crossbeam-epoch) are semver-compatible and resolve with a fresh cargo update. Cargo.lock isn't tracked, so this PR doesn't change them.

For the maintainer

  • The CHANGELOG release date is now 2026-10-18; adjust as needed.
  • #432 also appears under the already-released [0.14.1] - Fixed ("mdBook table of contents ordering"). That may be the wrong PR number; I left it unchanged.
  • ea7c2bf is a formatting-only commit. Nightly rustfmt 2026-10-16 re-wraps comments under wrap_comments, which was failing the Rustfmt job on about 10 files (it would fail on main too). It contains no code changes.
  • Not addressed here: RUSTDOCFLAGS="-D warnings" cargo doc --features all still fails on pre-existing issues that this PR leaves unchanged:
    • two unresolved intra-doc links (ExporterSyncExt/ExporterAsyncExt) in plot.rs, which date back to fd36405;
    • several unclosed HTML tag <n> errors.

Test plan

  • cargo clippy --features all --all-targets -- -D warnings (no longer needs -A deprecated)
  • cargo clippy -p plotly_static --features geckodriver,webdriver_download -- -D warnings
  • cargo clippy --package plotly --target wasm32-unknown-unknown -- -D warnings
  • cargo test -p plotly --features all --lib: 379 pass. The 8 browser-dependent export tests couldn't run locally (chromedriver 153 vs Chrome 155); CI installs a matched pair.
  • cargo test -p plotly --features all --doc (38 pass), cargo test -p plotly_static --doc --features chromedriver (20 pass)
  • cd examples && cargo clippy --workspace -- -D warnings
  • cargo clippy --workspace --all-targets --features all -- -A clippy::all -W clippy::missing_panics_doc -W clippy::missing_errors_doc -W clippy::non_std_lazy_statics -W clippy::doc_markdown (also with static_export_geckodriver and --target wasm32-unknown-unknown): clean
  • typos
  • cargo audit: only the transitive zip 8.6.0 advisories described above remain
  • Trace coverage commits: cargo test --workspace --features plotly_ndarray,plotly_image,static_export_default,debug --exclude plotly_kaleido -- --test-threads=1 passes (418 lib tests). Every commit passes the plotly tests, native clippy, nightly fmt and a build of its example crates. wasm32 clippy, typos and the full examples workspace build are clean on the final commit.
  • Each new trace's example rendered and checked visually in Chrome against plotly.js 3.7.0.
  • cargo-semver-checks (my local version can't read this toolchain's rustdoc format; relying on the CI job). Expected breaking items: new PlotType and ThetaUnit variants and the LightPosition field types.

🤖 Generated with Claude Code

jqnatividad and others added 6 commits October 17, 2026 11:50
Both were deprecated in 0.13.0 with removal announced for 0.15.0.

- Drop the plotly_kaleido crate from the workspace, the `kaleido` and
  `kaleido_download` features, and the kaleido-gated Plot methods.
- Drop `ImageFormat::EPS` from plotly_static and the
  `#![allow(deprecated)]` that was waiting on 0.15.0.
- Remove the kaleido example, its CI matrix entries, the
  publish_plotly_kaleido workflow and the release publish step; run the
  semver check against `static_export_chromedriver` instead.
- Remove kaleido/EPS sections from README and the book, and point the
  install snippets at 0.15.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- plotly_static: remove the `zip` build-dependency, which build.rs never
  used; bump `dirs` 6 -> 7.
- plotly_derive: bump `darling` 0.23 -> 0.24 together with `syn` 2 -> 3,
  since darling 0.24 is built on syn 3. No macro code changes needed.
- examples: bump reqwest 0.11 -> 0.13, env_logger 0.10 -> 0.11,
  itertools 0.12 -> 0.15, ndarray 0.15 -> 0.17 and rand/rand_chacha
  0.8/0.3 -> 0.10, adapting to `RngExt::random` and dropping the
  deprecated `into_raw_vec`.

zip 8.x is still pulled in transitively by webdriver-downloader 0.17
(`zip ^8`) until ik1ne/webdriver-downloader#67 is released.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- plotly 0.14.1 -> 0.15.0, plotly_derive 0.14.1 -> 0.15.0
- plotly_static 0.1.0 -> 0.2.0 (EPS removal is breaking; also carries
  the plotly.js 3.7.0 bundle)
- Promote [Unreleased] to [0.15.0] in the CHANGELOG, add Removed and
  Security sections, and drop duplicated Funnel/Waterfall entries.

Last release on plotly.js 3.x; plotly.js 4.x follows in 0.16.0 (plotly#437).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A pinned `release-type: minor` is applied verbatim, without the 0.y.z
promotion, so the intentional removals in 0.15.0 (kaleido features and
methods, `ImageFormat::EPS`) would fail as major-level changes. Inferring
from the version bump treats 0.14.1 -> 0.15.0 as major, while unchanged
versions during development still default to a minor-level check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The trace loop used `0..=num_steps`, creating 52 traces (frequencies
0.0-5.1) while each slider step's visibility mask has 51 entries, so
step 0 also showed the stray 5.1 curve. Use `0..num_steps` to match.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The current nightly rustfmt re-wraps comments under the repo's
`wrap_comments` setting, which fails the Rustfmt CI job. Formatting
only; no code changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Address clippy::missing_panics_doc, missing_errors_doc, doc_markdown,
non_std_lazy_statics and cargo::redundant_homepage:

- Add `# Errors` / `# Panics` sections to public fallible APIs,
  including the wasm-only bindings and callbacks.
- Backtick identifiers in docs and fix unbalanced backticks; add
  clippy.toml whitelisting WebDriver, MapLibre, GeoJSON, MathJax and
  ModeBar as product names.
- Switch theme statics to std::sync::LazyLock and drop once_cell.
- Remove `homepage` fields duplicating `repository`.

Also fix Plot::add_frames adding every frame twice when the plot had
no frames yet, with a regression test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
jqnatividad added a commit to dathere/qsv that referenced this pull request Oct 17, 2026
)

* deps: use plotly.rs 0.15.0 release branch (plotly/plotly.rs#442); regenerate viz gallery

Point the plotly [patch] at the 0.15.0 release-prep PR head
(dathere/plotly@a21da1f) and bump the plotly requirement to 0.15 so the
patch applies. This pulls in plotly_derive 0.15.0 and plotly_static 0.2.0,
and drops darling 0.23 and lzma-rust2 (via plotly's removed zip
build-dependency). qsv does not use the removed Kaleido backend or
ImageFormat::EPS. The embedded plotly.js bundle is unchanged (3.7.0).

Regenerated the viz gallery with gen_gallery.py: gallery.html is
byte-identical; 14 smart dashboards pick up the 25.0.0 compile stamp, and
two map pages (smart_us_choropleth, smart_world_events) get richer hover
place names from the 25.0.0 geocode index.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(changelog): note plotly.rs 0.15.0 (#4836)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@jqnatividad
jqnatividad marked this pull request as draft October 18, 2026 11:43
jqnatividad and others added 6 commits October 18, 2026 08:11
- BarPolar: bars on a polar subplot (wind roses). Adds per-subplot
  `LayoutPolar::bar_mode`/`bar_gap` (`PolarBarMode`), which plotly.js
  reads from `layout.polar`, and `ThetaUnit::Gradians`.
- FunnelArea: pie-like funnel with `FunnelAreaTitle`; adds the
  `funnelareacolorway`, `extendfunnelareacolors` and `hiddenlabels`
  layout attributes.
- Wind rose and funnel area examples plus book recipe pages.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tly#422)

- Cone and StreamTube for 3D vector fields; IsoSurface and Volume for
  3D scalar fields, sharing the Caps/Slices/SpaceFrame/IsoSurfaceSurface
  sub-structs. Volume adds an `OpacityScale`.
- All four reuse `mesh3d::Lighting` and `mesh3d::LightPosition`.
- BREAKING: `mesh3d::LightPosition` x/y/z are now `f64` instead of
  `Vec<f64>`. plotly.js expects a single number per coordinate and
  silently ignored the arrays, so Mesh3D light positions never took
  effect.
- Vector field and volume examples plus book recipe pages.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Parallel coordinates with a numeric `Dimension` (range, multiselect and
a `ConstraintRange` for single or multiple brushed intervals), a
`ParcoordsLine` color scale and `Unselected` line styling. Includes an
example and book recipe page.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…plotly#422)

- New ternary subplot: `LayoutTernary` with `TernaryAxis` for the a/b/c
  axes, replacing the commented-out `ternary` stub on `Layout`.
- New Smith chart subplot: `LayoutSmith` with `RealAxis` and
  `ImaginaryAxis`.
- ScatterTernary and ScatterSmith traces on those subplots.
- Ternary and Smith chart examples plus book recipe pages.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tly#422)

- Carpet: an a/b coordinate system on cartesian axes, styled with
  `CarpetAxis`. x/y accept 1D or 2D data via `CarpetCoordinates`.
- ScatterCarpet and ContourCarpet are drawn on a carpet referenced by
  its `carpet` id; ContourCarpet reuses `contour::Contours`.
- Carpet examples plus a book recipe page.

This completes plotly.js 3.7 trace-type coverage.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Record the plotly#422 trace types, ternary/Smith subplots and the breaking
mesh3d `LightPosition` fix, add a highlights summary, and move the
release date to 2026-10-18.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@jqnatividad jqnatividad changed the title Release 0.15.0: plotly.js 3.x work, remove kaleido/EPS, dependency security bumps Release 0.15.0: complete plotly.js 3.7 trace coverage, remove kaleido/EPS, dependency security bumps Oct 18, 2026
jqnatividad and others added 2 commits October 18, 2026 08:34
- TernaryAxis, RealAxis, ImaginaryAxis and CarpetAxis: `label_alias` is
  now a `HashMap<String, String>`. plotly.js deletes `labelalias` unless
  it is a plain object, so the previous string values were ignored.
- StreamTube: correct the documented default starting positions (the
  x-z plane at the lowest y, not the lowest x).
- Book: show the `grid_3d` helper used by the vector field and volume
  recipes, so the examples are reproducible.
- FunnelArea example: use `percent` in `text_info`; funnelarea does not
  support `percent initial`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`PlotType::Histogram2dContour` existed, but no trace could emit it, so
plotly.js's `histogram2dcontour` was unreachable. The new trace shares
Histogram2d's binning API, adds the contour attributes (`autocontour`,
`ncontours`, `contours` reusing `contour::Contours`, and `line`), and
exposes `ids`, `coloraxis` and the bin-group attributes.

Includes an example, a section on the 2D histograms book page, and the
CHANGELOG update (27 trace types new since 0.14.1).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@jqnatividad

jqnatividad commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor Author

Hi @andrei-ng , I did the plotly.js 3.7 as v15.0.0 release prep as discussed (#437), and decided to go the stretch goal of completing trace coverage :) #426

Doing so should make for comprehensive plotly.js 3.7 coverage on 15.x, and put us in a good position to upgrade to plotly.js 4.x in 16.x.

@andrei-ng

andrei-ng commented Oct 18, 2026 •

Copy link
Copy Markdown
Collaborator

@jqnatividad , thanks for the work and the PR! I had a quick look and in general it looks spot on. I'll review it properly by the end of the week and merge it.

jqnatividad and others added 2 commits October 18, 2026 13:00
…ing null

LayoutPolar, RadialAxis, AngularAxis, PolarAxisAttributes,
PolarAxisTicks, AutoRangeOptions, PolarTickMode and geo Rotation lacked
skip_serializing_none, so every unset field went out as `null`.
plotly.js applies a layout template only to absent attributes, so the
nulls overrode the theme: a polar subplot on plotly_dark drew a white
background (`bgcolor` resolved to #fff).

Adds serialization tests asserting unset fields are omitted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PLOTLY_DARK had no polar or ternary section, so plotly.js fell back to
its white defaults and drew a white disc/triangle on the dark paper
(e.g. a ScatterPolar radar or BarPolar wind rose). Add both, matching
plotly.py's plotly_dark: rgb(17,17,17) background, #506784 grid and
axis lines, no tick marks.

Also reword the 0.15.0 changelog entry for 43a4ee4: omitting null
fields is a cleanup, not the cause of the white background.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
jqnatividad added a commit to dathere/qsv that referenced this pull request Oct 18, 2026
… 3.7 traces) (#4838)

* deps: pin plotly.rs fork to plotly/plotly.rs#442 head (full plotly.js 3.7 traces)

Moves the dathere/plotly pin from a21da1f to 55555b2, the final commit of the
0.15.0 release branch. The new commits add the remaining 13 plotly.js 3.7 trace
types; the only breaking change (mesh3d::LightPosition) is not used by qsv.
Only plotly, plotly_derive and plotly_static move in Cargo.lock.

Verified: viz unit + integration suites pass, qsvmcp (viz_static) builds, and a
full gallery regen differs only in per-run timestamps.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(changelog): cite #4838

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants