rbplotly 0.1.2 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +88 -0
  3. data/LICENSE.txt +1 -1
  4. data/README.md +213 -50
  5. data/lib/plotly/assets/plotly.min.js +3620 -0
  6. data/lib/plotly/attributes.rb +221 -0
  7. data/lib/plotly/figure.rb +292 -0
  8. data/lib/plotly/frames.rb +38 -0
  9. data/lib/plotly/html.rb +161 -0
  10. data/lib/plotly/plot.rb +11 -28
  11. data/lib/plotly/schema/plot-schema.json +57258 -0
  12. data/lib/plotly/schema.rb +99 -0
  13. data/lib/plotly/serializer.rb +49 -0
  14. data/lib/plotly/subplots.rb +186 -0
  15. data/lib/plotly/version.rb +7 -1
  16. data/lib/plotly.rb +22 -0
  17. data/lib/rbplotly.rb +3 -4
  18. metadata +35 -179
  19. data/.gitignore +0 -11
  20. data/.rspec +0 -2
  21. data/.rubocop.yml +0 -22
  22. data/.travis.yml +0 -9
  23. data/CODE_OF_CONDUCT.md +0 -49
  24. data/Gemfile +0 -4
  25. data/Guardfile +0 -12
  26. data/Rakefile +0 -9
  27. data/bin/console +0 -14
  28. data/bin/setup +0 -8
  29. data/docs/images/line_chart.png +0 -0
  30. data/examples/Bar Charts.ipynb +0 -254
  31. data/examples/Basic Usage.ipynb +0 -227
  32. data/examples/Histograms.ipynb +0 -79
  33. data/examples/Line charts.ipynb +0 -88
  34. data/examples/Pie Charts.ipynb +0 -151
  35. data/examples/Scatter Plots.ipynb +0 -224
  36. data/examples/heatmaps.ipynb +0 -150
  37. data/lib/plotly/axis.rb +0 -18
  38. data/lib/plotly/castable.rb +0 -20
  39. data/lib/plotly/client.rb +0 -45
  40. data/lib/plotly/data.rb +0 -33
  41. data/lib/plotly/exportable.rb +0 -23
  42. data/lib/plotly/layout.rb +0 -33
  43. data/lib/plotly/line.rb +0 -17
  44. data/lib/plotly/marker.rb +0 -23
  45. data/lib/plotly/offline/exportable.rb +0 -36
  46. data/lib/plotly/offline/html.rb +0 -46
  47. data/lib/plotly/offline/plotly.min.js +0 -59
  48. data/lib/plotly/offline/templates/body.erb +0 -26
  49. data/lib/plotly/offline/templates/plot.erb +0 -12
  50. data/lib/plotly/util.rb +0 -11
  51. data/rbplotly.gemspec +0 -35
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: a5824c809b3bf7260b81eacf6b77ab986ab93f5e
4
- data.tar.gz: 7199d7e10c9fa43b2cf61f601e68db6b1949e3c2
2
+ SHA256:
3
+ metadata.gz: 3ee3bc96889cfdc7042b4cb2d4f493003ede009bb78ac14f59b2ff78aa56345c
4
+ data.tar.gz: e395c9e2230df5996b6a91a1757b4d72cd9829149aad82e7ba0acc3dac066c60
5
5
  SHA512:
6
- metadata.gz: e37858b56eff737d8622fa3d8c4304370cf16805717df885cc197dfcf472e78d3f47a76d41a9ef55a9410a5f17751494c877d4f156a40edc4cb83c740114b34a
7
- data.tar.gz: e7e11ff2ae577e8eb5a91831915196067faa028d54a0275704f75b4c37bdb294ae33639093ce67bb1a345079615600c23402aa291d59667e582aa35f8e8d4d01
6
+ metadata.gz: c05da261022f1d36806155a0f1f004e17c020e5451b79daf09daeb8f28d2820fd0cd90aa73444109c0516fd6b126745a74b28fa721261e941572fb857e9f7288
7
+ data.tar.gz: 46fa94b5913d6dfc0b37a5dd5761c59f7c775823b6bc02c41630c94ee7995d418d4676268086a6652fdd1a680c256a0f1205ef044a19892ac2bc5c47d992a306
data/CHANGELOG.md ADDED
@@ -0,0 +1,88 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented here. The format follows
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and versions follow
5
+ [Semantic Versioning](https://semver.org/).
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [1.0.1] - 2026-10-07
10
+
11
+ ### Added
12
+
13
+ - Relative subplot sizes through `column_widths` and `row_heights`, and per-cell right y
14
+ axes through `specs: [[{secondary_y: true}]]`. Trace placement, trace updates and y-axis
15
+ updates accept `secondary_y`; existing primary axis numbering is preserved.
16
+ - Animation frames through `Figure.new(frames:)`, `add_frame` and `frames=`, with validation
17
+ of partial trace/layout updates and inclusion in JSON output. HTML and notebook output
18
+ register frames and start playback; `to_html` and `write_html` accept `auto_play` and
19
+ `animation_opts`.
20
+ - Runnable examples for secondary axes and animation.
21
+
22
+ ### Fixed
23
+
24
+ - Require `json >= 2.9` to avoid the older `script_safe` bug that corrupts characters such
25
+ as `瀨` and `倩` in chart labels and JSON output.
26
+ - Reject negative, non-finite and out-of-range subplot spacing instead of silently
27
+ overlapping or collapsing cells; reject invalid row/column counts before calculating defaults.
28
+
29
+ ## [1.0.0] - 2026-10-07
30
+
31
+ A rewrite. Figures are now plain hashes checked against the plot schema of a pinned
32
+ plotly.js release, instead of hand-written classes that covered a few attributes.
33
+
34
+ ### Added
35
+
36
+ - `Plotly::Figure` with `add_trace`, an `add_<type>` helper for each of plotly.js' 47 trace
37
+ types, `update_layout`, `update_traces` (with `selector:`), `update_xaxes`, `update_yaxes`
38
+ and `update_config`.
39
+ - Validation of attribute names, enumerated values, flag lists, booleans and number ranges
40
+ against plotly.js 4.1.2, with the attribute path and a spelling suggestion in
41
+ `Plotly::ValidationError`. `validate: false` turns it off.
42
+ - Underscore paths for nested attributes: `marker_line_width: 2`.
43
+ - `Plotly.make_subplots` with shared axes and subplot titles; `row:` / `col:` on trace and
44
+ axis updates.
45
+ - `include_plotlyjs:` (`:cdn`, `:inline`, `false` or a URL), `div_id:`, `width:`, `height:`
46
+ and `full_html:` on `to_html`; `write_html` embeds plotly.js by default so files work offline.
47
+ - `to_json` / `to_h`. Dates and times, `NaN`, ranges, `BigDecimal` and objects with `#to_a`
48
+ (Numo, Polars, Daru columns) are converted to what plotly.js expects.
49
+ - An example gallery (`rake gallery`) and specs that draw the generated HTML in headless Chrome.
50
+
51
+ ### Changed
52
+
53
+ - Requires Ruby 3.3 or later.
54
+ - Bundles plotly.js 4.1.2 (was 1.16.2). The CDN URL is pinned to the same release instead of
55
+ `plotly-latest`, which stopped updating at 1.x.
56
+ - JSON inside `<script>` is escaped so that strings such as `"</script>"` cannot end the
57
+ element.
58
+ - Charts resize with their container through plotly.js' `responsive` config.
59
+ - No runtime dependencies besides `json` (`faraday`, `uuidtools` and `launchy` are gone).
60
+
61
+ ### Fixed
62
+
63
+ - Charts render in JupyterLab: notebook output no longer relies on RequireJS, and
64
+ `to_iruby_mimebundle` keeps IRuby 0.8 from choosing `to_html`, whose script would run
65
+ before plotly.js loads ([#10](https://github.com/ash1day/rbplotly/issues/10)).
66
+ - Subplots are supported ([#8](https://github.com/ash1day/rbplotly/issues/8)).
67
+ - Tests run without a plot.ly account, and the README explains how to run them
68
+ ([#9](https://github.com/ash1day/rbplotly/issues/9)).
69
+
70
+ ### Deprecated
71
+
72
+ - `Plotly::Plot`. It still accepts `data:` / `layout:` and `generate_html(path:, open:)`,
73
+ and prints a warning; use `Plotly::Figure` and `write_html`. It will be removed in 2.0.
74
+
75
+ ### Removed
76
+
77
+ - `Plotly.auth`, `Plotly::Client` and `#download_image`, which used the plot.ly cloud API.
78
+ - The attribute classes (`Plotly::Data`, `Layout`, `Axis`, `Marker`, `Line`) and
79
+ `Object#convert_to`, which was added to every object.
80
+
81
+ ## [0.1.2] - 2017-05-24
82
+
83
+ The last 0.x release. See the [git history](https://github.com/ash1day/rbplotly/commits/v0.1.2).
84
+
85
+ [Unreleased]: https://github.com/ash1day/rbplotly/compare/v1.0.1...HEAD
86
+ [1.0.1]: https://github.com/ash1day/rbplotly/compare/v1.0.0...v1.0.1
87
+ [1.0.0]: https://github.com/ash1day/rbplotly/compare/v0.1.2...v1.0.0
88
+ [0.1.2]: https://github.com/ash1day/rbplotly/releases/tag/v0.1.2
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2016 y4ashida
3
+ Copyright (c) 2016-2026 Yoshihiro Ashida
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,88 +1,251 @@
1
- [![Gem Version](https://badge.fury.io/rb/rbplotly.svg)](https://badge.fury.io/rb/rbplotly)
2
- [![Dependency Status](https://gemnasium.com/badges/github.com/ash1day/rbplotly.svg)](https://gemnasium.com/github.com/ash1day/rbplotly)
3
- [![Build Status](https://travis-ci.org/ash1day/rbplotly.svg?branch=master)](https://travis-ci.org/ash1day/rbplotly)
4
- [![Test Coverage](https://codeclimate.com/github/ash1day/rbplotly/badges/coverage.svg)](https://codeclimate.com/github/ash1day/rbplotly/coverage)
5
- [![Code Climate](https://codeclimate.com/github/ash1day/rbplotly/badges/gpa.svg)](https://codeclimate.com/github/ash1day/rbplotly)
1
+ # rbplotly
6
2
 
7
- # Rbplotly
3
+ [![Gem Version](https://img.shields.io/gem/v/rbplotly)](https://rubygems.org/gems/rbplotly)
4
+ [![CI](https://github.com/ash1day/rbplotly/actions/workflows/ci.yml/badge.svg)](https://github.com/ash1day/rbplotly/actions/workflows/ci.yml)
8
5
 
9
- Rbplotly, a Ruby visualization library, allows you to create interactive plots.
6
+ **Interactive [Plotly.js](https://plotly.com/javascript/) charts from Ruby.** Hover, zoom and
7
+ pan in the browser, from a few lines of plain Ruby, in a single HTML file you can send anyone.
10
8
 
11
- ## Installation
9
+ <img src="docs/images/hero.gif" width="800" alt="Hovering over a line chart made with rbplotly shows the values for each day; dragging zooms into a range and a double-click zooms back out">
12
10
 
13
- Add this line to your application's Gemfile:
11
+ ## Why rbplotly
14
12
 
15
- ```ruby
16
- gem 'rbplotly'
13
+ - **All of plotly.js, nothing invented.** Every chart type (47 of them, from bar charts to 3D
14
+ surfaces, Sankey diagrams and maps) and every attribute in the
15
+ [plotly.js reference](https://plotly.com/javascript/reference/) works as written there.
16
+ Plotly publishes no Ruby library; rbplotly is that missing layer.
17
+ - **Mistakes stop at the line that made them.** Figures are checked against the schema of the
18
+ bundled plotly.js release, so a typo raises an error with the attribute path and a
19
+ suggestion instead of producing a chart that silently ignores it.
20
+ - **Nothing to sign up for.** Output is HTML: one self-contained file that works offline, a
21
+ fragment for a Rails view, or inline output in Jupyter. No account, API key or server.
22
+
23
+ ## Quick start
24
+
25
+ ```sh
26
+ gem install rbplotly # Ruby 3.3+; or add gem "rbplotly" to your Gemfile
17
27
  ```
18
28
 
19
- And then execute:
29
+ ```ruby
30
+ require "rbplotly"
20
31
 
21
- $ bundle
32
+ weeks = (1..12).to_a
33
+ plan = [12, 14, 13, 17, 16, 19, 21, 20, 23, 25, 24, 28]
34
+ actual = [10, 15, 13, 18, 17, 18, 23, 22, 22, 27, 26, 31]
22
35
 
23
- Or install it yourself as:
36
+ fig = Plotly::Figure.new
37
+ .add_bar(x: weeks, y: plan, name: "Plan", marker_color: "#c7d2fe")
38
+ .add_scatter(x: weeks, y: actual, name: "Actual", mode: :"lines+markers", line_width: 3)
39
+ .update_layout(title_text: "Weekly sales", xaxis_title_text: "Week",
40
+ yaxis_title_text: "Units", hovermode: "x unified")
24
41
 
25
- $ gem install rbplotly
42
+ fig.write_html("sales.html") # add open: true to open it in your browser
43
+ ```
26
44
 
27
- ## Usage
45
+ <img src="docs/images/quick-start.png" width="800" alt="The chart the code above draws: planned sales as light bars and actual sales as a line over twelve weeks">
46
+
47
+ `sales.html` is a single file with plotly.js embedded: open it offline, attach it to an email,
48
+ or publish it as is.
49
+
50
+ ## Mistakes stop where you made them
28
51
 
29
52
  ```ruby
30
- require 'rbplotly'
53
+ fig.add_scatter(x: [1, 2], y: [3, 1], mode: :line)
54
+ # => Plotly::ValidationError: data[2].mode: "line" is not a flag of mode. Did you mean "lines"?
55
+ # Join "lines", "markers", "text" with "+", or use "none"
56
+ fig.update_layout(barmode: :stacked)
57
+ # => Plotly::ValidationError: layout.barmode: "stacked" is not one of "stack", "group",
58
+ # "overlay", "relative". Did you mean "stack"?
59
+ fig.add_bar(y: [1], marker_colour: "red")
60
+ # => Plotly::ValidationError: data[2].marker.colour: marker has no attribute "colour".
61
+ # Did you mean "color"?
62
+ fig.update_layout(title: "Sales")
63
+ # => Plotly::ValidationError: layout.title: expected a Hash of title attributes, got "Sales".
64
+ # Plotly.js no longer accepts a plain string here:
65
+ # use title: {text: "Sales"} or title_text: "Sales"
66
+ ```
67
+
68
+ Validation covers attribute names, enumerated values, flag lists, booleans and number ranges.
69
+ It is stricter than plotly.js on purpose: values that plotly.js would quietly replace with a
70
+ default are reported instead. Colors, data arrays and free-form values are passed through.
71
+ Of the 1308 test figures in plotly.js itself, 1204 pass; the rest contain such ignored input. If you need an attribute from a
72
+ newer plotly.js than the bundled one, turn validation off for that figure:
73
+ `Plotly::Figure.new(validate: false)`.
31
74
 
32
- x = [0, 1, 2, 3, 4]
33
- trace0 = { x: x, y: [0, 2, 1, 4, 3], type: :scatter, mode: :lines }
34
- trace1 = { x: x, y: [4, 1, 3, 0, 2], type: :scatter, mode: :'markers+lines' }
35
- data = [trace0, trace1] # data must be an array
75
+ ## Gallery
36
76
 
37
- layout = { width: 500, height: 500 }
77
+ <table>
78
+ <tr>
79
+ <td><a href="https://ash1day.github.io/rbplotly/#surface"><img src="docs/images/surface.png" width="400" alt="A 3D surface plot"></a></td>
80
+ <td><a href="https://ash1day.github.io/rbplotly/#sankey"><img src="docs/images/sankey.png" width="400" alt="A Sankey diagram of visitor flows"></a></td>
81
+ </tr>
82
+ <tr>
83
+ <td><a href="https://ash1day.github.io/rbplotly/#sunburst"><img src="docs/images/sunburst.png" width="400" alt="A sunburst chart of a budget split by group and team"></a></td>
84
+ <td><a href="https://ash1day.github.io/rbplotly/#distributions"><img src="docs/images/distributions.png" width="400" alt="Histograms and box plots of response times sharing an axis"></a></td>
85
+ </tr>
86
+ </table>
38
87
 
39
- plot = Plotly::Plot.new(data: data, layout: layout)
88
+ **[See every example running, next to its code →](https://ash1day.github.io/rbplotly/)**
40
89
 
41
- plot.layout.height = 300 # You can assign plot's attributes.
90
+ ## Building figures
42
91
 
43
- plot.generate_html(path: './line_chart.html')
92
+ A figure has traces (`data`), a `layout` and a plotly.js `config`. Attribute names are those
93
+ of the [plotly.js reference](https://plotly.com/javascript/reference/); rbplotly adds no names
94
+ of its own.
95
+
96
+ ```ruby
97
+ fig = Plotly::Figure.new(
98
+ data: [{type: :bar, x: %w[A B C], y: [3, 1, 2]}],
99
+ layout: {title: {text: "Votes"}, height: 400}
100
+ )
101
+
102
+ # One add_<type> helper per trace type: add_scatter, add_bar, add_heatmap, add_sankey, ...
103
+ fig.add_scatter(x: %w[A B C], y: [2, 2, 2], mode: :lines, name: "Target")
104
+
105
+ # Underscores reach into nested attributes:
106
+ # marker_line_width: 2 is marker: {line: {width: 2}}
107
+ fig.update_traces({marker_color: "teal", marker_line_width: 1}, selector: {type: :bar})
108
+ fig.update_layout(yaxis_range: [0, 4], legend_orientation: "h")
44
109
  ```
45
110
 
46
- <img src="./docs/images/line_chart.png" width="400">
111
+ Names that contain an underscore themselves (`error_x`, `paper_bgcolor`) keep working.
112
+ Updates merge into what is already there.
47
113
 
48
- Use `#download_image` if you want to get an image by using Plot.ly API. You can get your API KEY [here](https://plot.ly/settings/api).
114
+ ### Subplots
49
115
 
50
116
  ```ruby
51
- Plotly.auth(<YOUR_USERNAME>, <YOUR_API_KEY>)
52
- plot.download_image(path: './line_chart.png')
117
+ fig = Plotly.make_subplots(rows: 1, cols: 2, subplot_titles: ["Revenue", "Users"])
118
+ fig.add_bar(x: %w[Q1 Q2 Q3], y: [10, 12, 15], row: 1, col: 1)
119
+ fig.add_scatter(x: %w[Q1 Q2 Q3], y: [200, 260, 310], row: 1, col: 2)
120
+ fig.update_yaxes({title_text: "USD (M)"}, row: 1, col: 1)
53
121
  ```
54
122
 
55
- Or use `#show` on IRuby notebooks.
123
+ `shared_xaxes:` and `shared_yaxes:` link the axes of a column or row so they zoom together.
124
+ Traces on x/y axes go on the cell's axes and domain traces (pie, sunburst, ...) fill the cell;
125
+ 3D, polar, ternary and map traces cannot be placed by `row:`/`col:` yet.
126
+
127
+ Use positive relative `column_widths:` and `row_heights:` to size cells. Row heights are
128
+ ordered from top to bottom; spacing is subtracted before distributing the remaining space.
129
+ Enable a right y axis with `specs:`, then select it with `secondary_y: true`:
130
+
131
+ ```ruby
132
+ fig = Plotly.make_subplots(cols: 2, column_widths: [2, 1],
133
+ specs: [[{secondary_y: true}, {}]])
134
+ fig.add_bar(x: %w[Jan Feb Mar], y: [100, 150, 180], name: "Orders", row: 1, col: 1)
135
+ fig.add_scatter(x: %w[Jan Feb Mar], y: [2, 3, 2.5], name: "Conversion %",
136
+ row: 1, col: 1, secondary_y: true)
137
+ fig.update_yaxes(title_text: "Orders", row: 1, col: 1, secondary_y: false)
138
+ fig.update_yaxes(title_text: "Conversion", ticksuffix: "%", secondary_y: true)
139
+ ```
140
+
141
+ `specs` currently accepts only `secondary_y` in each cell hash. Existing primary axis
142
+ numbers stay unchanged; secondary axes are numbered after all primary axes.
143
+ `update_traces` and `update_yaxes` accept `secondary_y: true` (right), `false` (left),
144
+ or the default `nil` (both). Axis sharing links only primary axes.
145
+
146
+ ### Animation
147
+
148
+ Supply `frames:` to the constructor, append with `add_frame`, or replace with `frames=`.
149
+ Define base traces before frames: omitted trace types are inferred from the corresponding
150
+ base trace. A frame's `traces` array maps its data entries to zero-based trace indices.
56
151
 
57
152
  ```ruby
58
- plot.show
153
+ fig = Plotly::Figure.new.add_scatter(x: [0, 1], y: [0, 1], mode: :"lines+markers")
154
+ fig.update_layout(xaxis_range: [0, 1], yaxis_range: [0, 3])
155
+ fig.add_frame(name: "first", data: [{y: [1, 2]}])
156
+ fig.add_frame(name: "second", data: [{y: [2, 3]}])
157
+ fig.write_html("animation.html", animation_opts: {frame: {duration: 700}, transition: {duration: 300}})
59
158
  ```
60
159
 
61
- ## Examples
160
+ HTML and notebook output register frames after drawing, then play them automatically.
161
+ Pass `auto_play: false` to `to_html` or `write_html` to register frames without starting;
162
+ use layout `updatemenus`/`sliders` or JavaScript to trigger playback. Nonempty frames are
163
+ included in `to_h` and `to_json`. Without base data, an omitted trace type defaults to scatter.
62
164
 
63
- - [Basic Usage](https://nbviewer.jupyter.org/github/ash1day/rbplotly/blob/master/examples/Basic%20Usage.ipynb)
64
- - [Bar Charts](https://nbviewer.jupyter.org/github/ash1day/rbplotly/blob/master/examples/Bar%20%20Charts.ipynb)
65
- - [Scatter Plots](https://nbviewer.jupyter.org/github/ash1day/rbplotly/blob/master/examples/Scatter%20Plots.ipynb)
66
- - [Line Charts](https://nbviewer.jupyter.org/github/ash1day/rbplotly/blob/master/examples/Line%20charts.ipynb)
67
- - [Pie Charts](https://nbviewer.jupyter.org/github/ash1day/rbplotly/blob/master/examples/Pie%20Charts.ipynb)
68
- - [Histograms](https://nbviewer.jupyter.org/github/ash1day/rbplotly/blob/master/examples/Histograms.ipynb)
69
- - [Heatmaps](https://nbviewer.jupyter.org/github/ash1day/rbplotly/blob/master/examples/heatmaps.ipynb)
165
+ ## Output
70
166
 
71
- Visit [here](https://nbviewer.jupyter.org/github/ash1day/rbplotly/tree/master/examples/) to see more examples.
167
+ | Method | Gives you |
168
+ | --- | --- |
169
+ | `fig.write_html(path)` | A standalone page with plotly.js embedded (works offline). `include_plotlyjs: :cdn` makes it ~5 MB smaller. |
170
+ | `fig.to_html` | An HTML fragment (`<div>` + `<script>`) that loads the pinned plotly.js from the CDN. |
171
+ | `fig.show` | The chart inline in a Jupyter notebook ([IRuby](https://github.com/SciRuby/iruby)), or in your browser otherwise. |
172
+ | `fig.to_json` / `fig.to_h` | The figure as plotly.js reads it, for your own front end or `Plotly.newPlot`. |
72
173
 
73
- ## Contributing
174
+ `include_plotlyjs:` accepts `:cdn`, `:inline`, `false` (the page already loads plotly.js) or a
175
+ URL. `to_html` also takes `div_id:`, `width:` and `height:` (Integers are pixels; the default
176
+ is the layout height, or 450px). Charts resize with their container.
74
177
 
75
- 1. Fork it
76
- 2. Create your feature branch (`git checkout -b my-new-feature`)
77
- 3. Commit your changes (`git commit -am 'Add some feature'`)
78
- 4. Push to the branch (`git push origin my-new-feature`)
79
- 5. Create new Pull Request
178
+ ### In a Rails view
80
179
 
81
- ## Thanks
180
+ ```erb
181
+ <%# Load plotly.js once in your layout, before this (not deferred), then: %>
182
+ <%= raw @figure.to_html(include_plotlyjs: false, height: 400) %>
183
+ ```
184
+
185
+ All strings in the figure are escaped for use inside `<script>`, so user-provided labels such
186
+ as `"</script>"` cannot break out of the page.
187
+
188
+ ### In Jupyter
189
+
190
+ With [IRuby](https://github.com/SciRuby/iruby), the last expression of a cell is displayed,
191
+ or call `fig.show`. plotly.js is loaded from the CDN once per notebook, without RequireJS
192
+ (which JupyterLab does not have, and which kept 0.x charts from showing there). Checked with
193
+ JupyterLab 4.6 and IRuby 0.8.
194
+
195
+ ## Data
196
+
197
+ Any of these can be used where plotly.js expects an array or a value:
198
+
199
+ - Arrays, Ranges (`x: 1..100`), Sets, Enumerators, and objects with `#to_a` such as
200
+ `Numo::NArray`, `Polars::Series` or `Daru::Vector`
201
+ - `Date` and `Time` (written as `"2026-10-06 09:30:00"`; plotly.js has no time zones, so it
202
+ shows the wall-clock time you give it)
203
+ - `Float::NAN` and infinities (written as `null`, which plotly.js draws as a gap)
204
+ - `BigDecimal` and `Rational` (written as floats), Symbols (written as strings)
205
+
206
+ Map traces that draw country outlines (`scattergeo`, `choropleth`) load them from Plotly's
207
+ CDN. Since plotly.js 3.1 those outlines come from
208
+ [UN Geodata](https://plotly.com/blog/improved-map-accuracy-plotlyjs-un-geodata/), which has
209
+ its own terms of use (attribution to the UN; no commercial use); check them before you publish
210
+ such a map.
211
+
212
+ ## plotly.js version
213
+
214
+ rbplotly 1.0 targets **plotly.js 4.1.2** (`Plotly::PLOTLY_JS_VERSION`). The CDN URL, the
215
+ embedded copy and the validation schema all come from that release, so what passes
216
+ validation is what the browser draws. New plotly.js releases ship as new rbplotly versions.
217
+
218
+ ## Not included
219
+
220
+ - **Static images (PNG/SVG/PDF).** Use the camera button in the chart's toolbar, or
221
+ `Plotly.toImage` in the browser. (The 0.x `download_image` used the plot.ly cloud API,
222
+ which no longer exists.)
223
+ - **A high-level "plot this data frame" API.** For seaborn-style statistical charts, see
224
+ [charty](https://github.com/red-data-tools/charty). rbplotly stays a faithful, typed layer
225
+ over plotly.js.
226
+
227
+ ## Upgrading from 0.x
228
+
229
+ 1.0 is a rewrite. `Plotly::Plot.new(data:, layout:)` still works and prints a deprecation
230
+ warning; `generate_html(path:)` is now `write_html(path)`. Attribute objects
231
+ (`plot.layout.height = 300`) are replaced by `update_layout(height: 300)`, and
232
+ `Plotly.auth` / `download_image` are removed. See [CHANGELOG.md](CHANGELOG.md).
233
+
234
+ ## Development
235
+
236
+ ```sh
237
+ git clone https://github.com/ash1day/rbplotly.git && cd rbplotly
238
+ bin/setup # bundle install + download the pinned plotly.js
239
+ bundle exec rake # specs + Standard (lint)
240
+ bundle exec rake spec:browser # draws generated HTML in headless Chrome (needs Chrome)
241
+ bundle exec rake gallery # builds the gallery into site/
242
+ ```
82
243
 
83
- `rbplotly` is based on [plotly/plotly.py](https://github.com/plotly/plotly.py), so there are a lot of code coming from it.
244
+ No API keys or accounts are needed to run anything. To move to a new plotly.js release, change
245
+ `PLOTLY_JS_VERSION` in `lib/plotly/version.rb`, put the output of `rake plotlyjs:checksum` into
246
+ `rakelib/plotlyjs.rake`, run `rake schema:generate`, and review the schema diff.
247
+ More in [CONTRIBUTING.md](CONTRIBUTING.md).
84
248
 
85
249
  ## License
86
250
 
87
- Copyright (c) 2016 Yoshihiro Ashida. See [LICENSE.txt](LICENSE.txt) for
88
- further details.
251
+ [MIT](LICENSE.txt). plotly.js, bundled in the gem, is © Plotly, Inc. and also MIT-licensed.