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
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ module Plotly
6
+ # The attribute tree of the bundled plotly.js release, generated by `rake schema:generate`.
7
+ class Schema
8
+ # The generated schema file.
9
+ PATH = File.expand_path("schema/plot-schema.json", __dir__)
10
+ # Numbered subplot ids: xaxis2, scene3 (plotly.js has no xaxis1).
11
+ SUBPLOT_SUFFIX = /\A(?<base>[a-z]+?)(?<n>[2-9]|[1-9]\d+)\z/
12
+
13
+ # One attribute: an object with children, an array of objects, or a leaf value.
14
+ class Node
15
+ attr_reader :name
16
+
17
+ def initialize(name, spec)
18
+ @name = name
19
+ @spec = spec
20
+ end
21
+
22
+ def object? = @spec.key?("attrs")
23
+
24
+ def array? = @spec.key?("array")
25
+
26
+ def leaf? = @spec.key?("type")
27
+
28
+ def subplot? = @spec["subplot"] == true
29
+
30
+ # @return [Array<String>] names of the children of an object
31
+ def attribute_names = @spec.fetch("attrs", {}).keys
32
+
33
+ # @return [Node, nil] the child attribute, or nil when plotly.js does not define it
34
+ def child(key)
35
+ attrs = @spec["attrs"] or return nil
36
+ key = key.to_s
37
+ return Node.new(key, attrs[key]) if attrs.key?(key)
38
+
39
+ match = SUBPLOT_SUFFIX.match(key) or return nil
40
+ base = attrs[match[:base]]
41
+ Node.new(key, base) if base&.fetch("subplot", false)
42
+ end
43
+
44
+ # @return [Node] the schema of each element of an array of objects
45
+ def item = Node.new(name.sub(/s\z/, ""), @spec.fetch("array"))
46
+
47
+ # @return [String, nil] plotly.js value type of a leaf: "number", "enumerated", "color", ...
48
+ def type = @spec["type"]
49
+
50
+ # @return [Array] allowed values of an enumerated leaf; "/.../" strings are patterns
51
+ def values = @spec.fetch("values", [])
52
+
53
+ # @return [Array<String>] flags of a flaglist leaf, joined with "+"
54
+ def flags = @spec.fetch("flags", [])
55
+
56
+ # @return [Array<String>] flaglist values that stand alone, such as "none"
57
+ def extras = @spec.fetch("extras", [])
58
+
59
+ # Whether the leaf also accepts an array of values, one per point.
60
+ def array_ok? = @spec["array_ok"] == true
61
+
62
+ # @return [Numeric, nil] lower bound of a number leaf
63
+ def min = @spec["min"]
64
+
65
+ # @return [Numeric, nil] upper bound of a number leaf
66
+ def max = @spec["max"]
67
+ end
68
+
69
+ # @return [Schema] the schema of the bundled plotly.js release, loaded once
70
+ def self.default
71
+ @default ||= new(JSON.parse(File.read(PATH)))
72
+ end
73
+
74
+ def initialize(raw)
75
+ @raw = raw
76
+ end
77
+
78
+ # @return [String] the plotly.js release the schema was generated from
79
+ def plotly_js_version = @raw.fetch("plotly_js")
80
+
81
+ # @return [Array<String>] every trace type: "bar", "scatter", ...
82
+ def trace_types = @raw.fetch("traces").keys
83
+
84
+ # @return [Node, nil]
85
+ def trace(type)
86
+ spec = @raw.fetch("traces")[type.to_s]
87
+ Node.new(type.to_s, spec) if spec
88
+ end
89
+
90
+ # @return [Node] layout attributes, including those trace types add (barmode, ...)
91
+ def layout = Node.new("layout", @raw.fetch("layout"))
92
+
93
+ # @return [Node] plotly.js config options
94
+ def config = Node.new("config", @raw.fetch("config"))
95
+
96
+ # @return [Node] attributes of an animation frame (data and layout are validated separately)
97
+ def frame = Node.new("frames", @raw.fetch("frames")).item
98
+ end
99
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "date"
4
+ require "json"
5
+
6
+ module Plotly
7
+ # Writes figures as the JSON that plotly.js reads.
8
+ module Serializer
9
+ module_function
10
+
11
+ # Characters escaped in JSON so it can be embedded in HTML.
12
+ HTML_UNSAFE = {"<" => "\\u003c", ">" => "\\u003e", "&" => "\\u0026"}.freeze
13
+
14
+ # @return [String] JSON that is safe to place inside an HTML <script> element: `<`, `>`
15
+ # and `&` (which only occur inside strings) and U+2028/2029 are written as escapes
16
+ def dump(value)
17
+ JSON.generate(plain(value), script_safe: true).gsub(/[<>&]/, HTML_UNSAFE)
18
+ end
19
+
20
+ # Converts a value into Hashes, Arrays, Strings, numbers, booleans and nils.
21
+ def plain(value)
22
+ case value
23
+ when Hash then value.to_h { |k, v| [k.to_s, plain(v)] }
24
+ when Array then value.map { |v| plain(v) }
25
+ when String, Integer, true, false, nil then value
26
+ when Symbol then value.to_s
27
+ when Float then value.finite? ? value : nil
28
+ when Complex then unsupported!(value)
29
+ when Numeric then plain(value.to_f)
30
+ when Time, DateTime then timestamp(value)
31
+ when Date then value.strftime("%Y-%m-%d")
32
+ when Struct then unsupported!(value) # a record, even though Struct#to_a exists
33
+ else
34
+ # Ranges, Sets, Enumerators and data frame columns (Numo::NArray, Polars::Series, ...)
35
+ value.respond_to?(:to_a) ? plain(value.to_a) : unsupported!(value)
36
+ end
37
+ end
38
+
39
+ # plotly.js has no time zones: a date string is drawn as the wall-clock time it names.
40
+ def timestamp(time)
41
+ fraction = time.strftime("%N").sub(/0+\z/, "")
42
+ time.strftime("%Y-%m-%d %H:%M:%S") + (fraction.empty? ? "" : ".#{fraction}")
43
+ end
44
+
45
+ def unsupported!(value)
46
+ raise TypeError, "#{value.inspect} (#{value.class}) cannot be written as plotly.js JSON"
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,186 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Plotly
4
+ # Builds a figure with a grid of subplots, each with its own x and y axis.
5
+ #
6
+ # Cells are numbered from the top-left, row by row; traces are placed with
7
+ # `add_trace(..., row:, col:)`. Spacing defaults follow plotly.py.
8
+ #
9
+ # @example
10
+ # fig = Plotly.make_subplots(rows: 1, cols: 2, subplot_titles: ["Revenue", "Users"])
11
+ # fig.add_bar(x: months, y: revenue, row: 1, col: 1)
12
+ # fig.add_scatter(x: months, y: users, row: 1, col: 2)
13
+ #
14
+ # @param rows [Integer]
15
+ # @param cols [Integer]
16
+ # @param shared_xaxes [Boolean] link the x axes of each column and label only the bottom one
17
+ # @param shared_yaxes [Boolean] link the y axes of each row and label only the left one
18
+ # @param subplot_titles [Array<String>, nil] one title per cell, in row-major order
19
+ # @param horizontal_spacing [Float] gap between columns, as a fraction of the figure width
20
+ # @param vertical_spacing [Float] gap between rows, as a fraction of the figure height
21
+ # @param column_widths [Array<Numeric>, nil] positive relative column widths, left to right
22
+ # @param row_heights [Array<Numeric>, nil] positive relative row heights, top to bottom
23
+ # @param specs [Array<Array<Hash>>, nil] one hash per cell; `secondary_y: true` adds a right y axis
24
+ # @param figure_options [Hash] passed to {Figure#initialize} (`layout:`, `config:`, `validate:`)
25
+ # @return [Figure]
26
+ def self.make_subplots(rows: 1, cols: 1, shared_xaxes: false, shared_yaxes: false, subplot_titles: nil,
27
+ horizontal_spacing: nil, vertical_spacing: nil, column_widths: nil, row_heights: nil, specs: nil, **figure_options)
28
+ grid = Subplots::Grid.new(rows, cols, horizontal_spacing, vertical_spacing,
29
+ column_widths: column_widths, row_heights: row_heights, specs: specs)
30
+ titles = Array(subplot_titles)
31
+ if titles.size > grid.cells.size
32
+ raise ArgumentError, "#{titles.size} subplot titles for #{grid.cells.size} cells"
33
+ end
34
+
35
+ figure = Figure.new(**figure_options)
36
+ figure.subplot_grid = grid
37
+ figure.update_layout(grid.axes_layout(shared_xaxes, shared_yaxes))
38
+ annotations = grid.title_annotations(titles)
39
+ figure.update_layout(annotations: (figure.layout["annotations"] || []) + annotations) if annotations.any?
40
+ figure
41
+ end
42
+
43
+ # Grid layout behind {Plotly.make_subplots}.
44
+ # @api private
45
+ module Subplots
46
+ Cell = Struct.new(:row, :col, :index, :x_domain, :y_domain, :secondary_index) do
47
+ def suffix = (index == 1) ? "" : index.to_s
48
+
49
+ def axis_ids(secondary_y = false) = ["x#{suffix}", secondary_y ? "y#{secondary_index}" : "y#{suffix}"]
50
+
51
+ def layout_key(letter) = "#{letter}axis#{suffix}"
52
+
53
+ def y_keys(secondary_y = nil)
54
+ keys = []
55
+ keys << layout_key("y") unless secondary_y == true
56
+ keys << "yaxis#{secondary_index}" if secondary_index && secondary_y != false
57
+ keys
58
+ end
59
+ end
60
+
61
+ class Grid
62
+ attr_reader :rows, :cols
63
+
64
+ def initialize(rows, cols, horizontal_spacing, vertical_spacing, column_widths: nil, row_heights: nil, specs: nil)
65
+ unless rows.is_a?(Integer) && cols.is_a?(Integer) && rows.positive? && cols.positive?
66
+ raise ArgumentError, "rows and cols must be positive integers"
67
+ end
68
+
69
+ @rows = rows
70
+ @cols = cols
71
+ horizontal_spacing = 0.2 / cols if horizontal_spacing.nil?
72
+ vertical_spacing = 0.3 / rows if vertical_spacing.nil?
73
+ horizontal_spacing = spacing(horizontal_spacing, cols, "horizontal_spacing")
74
+ vertical_spacing = spacing(vertical_spacing, rows, "vertical_spacing")
75
+ widths = sizes(column_widths, cols, 1.0 - horizontal_spacing * (cols - 1), "column_widths")
76
+ heights = sizes(row_heights, rows, 1.0 - vertical_spacing * (rows - 1), "row_heights")
77
+ secondary = secondary_cells(specs)
78
+ next_axis = rows * cols
79
+
80
+ y1 = 1.0
81
+ @cells = (1..rows).flat_map do |row|
82
+ x0 = 0.0
83
+ cells = (1..cols).map do |col|
84
+ second_axis = secondary[row - 1][col - 1] ? (next_axis += 1) : nil
85
+ cell = Cell.new(row, col, (row - 1) * cols + col,
86
+ domain(x0, x0 + widths[col - 1]), domain(y1 - heights[row - 1], y1), second_axis)
87
+ x0 += widths[col - 1] + horizontal_spacing
88
+ cell
89
+ end
90
+ y1 -= heights[row - 1] + vertical_spacing
91
+ cells
92
+ end
93
+ end
94
+
95
+ # @return [Array<Cell>] every cell, or the cells in the given row and/or column
96
+ def cells(row = nil, col = nil)
97
+ @cells.select { |c| (row.nil? || c.row == row) && (col.nil? || c.col == col) }
98
+ end
99
+
100
+ def cell(row, col)
101
+ found = cells(row, col)
102
+ return found.first if row && col && found.size == 1
103
+
104
+ raise ArgumentError, "row #{row.inspect}, col #{col.inspect} is outside the #{rows}x#{cols} subplot grid"
105
+ end
106
+
107
+ def axes_layout(shared_x, shared_y)
108
+ @cells.each_with_object({}) do |cell, layout|
109
+ x_id, y_id = cell.axis_ids
110
+ layout[cell.layout_key("x")] = {"domain" => cell.x_domain, "anchor" => y_id}.merge(
111
+ (shared_x && cell.row != rows) ? linked(cell(rows, cell.col).axis_ids[0]) : {}
112
+ )
113
+ layout[cell.layout_key("y")] = {"domain" => cell.y_domain, "anchor" => x_id}.merge(
114
+ (shared_y && cell.col != 1) ? linked(cell(cell.row, 1).axis_ids[1]) : {}
115
+ )
116
+ if cell.secondary_index
117
+ layout["yaxis#{cell.secondary_index}"] = {"anchor" => x_id, "overlaying" => y_id,
118
+ "side" => "right", "automargin" => true}
119
+ end
120
+ end
121
+ end
122
+
123
+ def title_annotations(titles)
124
+ titles.each_with_index.filter_map do |title, i|
125
+ next if title.nil? || title.to_s.empty?
126
+
127
+ cell = @cells[i]
128
+ {
129
+ "text" => title, "showarrow" => false, "font" => {"size" => 16},
130
+ "xref" => "paper", "yref" => "paper", "xanchor" => "center", "yanchor" => "bottom",
131
+ "x" => ((cell.x_domain[0] + cell.x_domain[1]) / 2).round(12), "y" => cell.y_domain[1]
132
+ }
133
+ end
134
+ end
135
+
136
+ private
137
+
138
+ def positive_number?(value)
139
+ value.is_a?(Numeric) && !value.is_a?(Complex) && value.finite? && value.positive?
140
+ end
141
+
142
+ def spacing(value, count, name)
143
+ unless value.is_a?(Numeric) && !value.is_a?(Complex) && value.finite? && value.between?(0, 1)
144
+ raise ArgumentError, "#{name} must be a finite number between 0 and 1"
145
+ end
146
+ raise ArgumentError, "spacing leaves no room for the subplots" unless value * (count - 1) < 1
147
+
148
+ value.to_f
149
+ end
150
+
151
+ def sizes(values, count, available, name)
152
+ values = Array.new(count, 1) if values.nil?
153
+ unless values.is_a?(Array) && values.size == count && values.all? { |v| positive_number?(v) }
154
+ raise ArgumentError, "#{name} must contain #{count} positive finite numbers"
155
+ end
156
+ largest = values.max
157
+ weights = values.map { |v| v.fdiv(largest) }
158
+ total = weights.sum
159
+ weights.map { |v| available * v / total }
160
+ end
161
+
162
+ def secondary_cells(specs)
163
+ return Array.new(rows) { Array.new(cols, false) } if specs.nil?
164
+ unless specs.is_a?(Array) && specs.size == rows && specs.all? { |row| row.is_a?(Array) && row.size == cols }
165
+ raise ArgumentError, "specs must be a #{rows}x#{cols} array of cell hashes"
166
+ end
167
+ specs.map do |row|
168
+ row.map do |spec|
169
+ unless spec.is_a?(Hash) && spec.keys.all? { |k| k.to_s == "secondary_y" }
170
+ raise ArgumentError, "each spec must be a Hash with only the secondary_y option"
171
+ end
172
+ value = spec.transform_keys(&:to_s).fetch("secondary_y", false)
173
+ raise ArgumentError, "secondary_y must be true or false" unless [true, false].include?(value)
174
+
175
+ value
176
+ end
177
+ end
178
+ end
179
+
180
+ # Follows another axis' range and leaves the tick labels to it.
181
+ def linked(axis_id) = {"matches" => axis_id, "showticklabels" => false}
182
+
183
+ def domain(from, to) = [from.round(12).clamp(0.0, 1.0), to.round(12).clamp(0.0, 1.0)]
184
+ end
185
+ end
186
+ end
@@ -1,3 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Plotly
2
- VERSION = '0.1.2'.freeze
4
+ # The gem version.
5
+ VERSION = "1.0.1"
6
+
7
+ # The plotly.js release this gem's schema, CDN URL and bundled script are built from.
8
+ PLOTLY_JS_VERSION = "4.1.2"
3
9
  end
data/lib/plotly.rb ADDED
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tmpdir"
4
+ require_relative "plotly/version"
5
+
6
+ # Interactive Plotly.js charts from Ruby.
7
+ module Plotly
8
+ # Raised when a figure uses an attribute or value that the bundled plotly.js schema rejects.
9
+ class ValidationError < ArgumentError; end
10
+
11
+ # Base class for other rbplotly errors.
12
+ class Error < StandardError; end
13
+ end
14
+
15
+ require_relative "plotly/schema"
16
+ require_relative "plotly/attributes"
17
+ require_relative "plotly/serializer"
18
+ require_relative "plotly/html"
19
+ require_relative "plotly/frames"
20
+ require_relative "plotly/figure"
21
+ require_relative "plotly/subplots"
22
+ require_relative "plotly/plot"
data/lib/rbplotly.rb CHANGED
@@ -1,4 +1,3 @@
1
- require 'plotly/version'
2
- require 'plotly/client'
3
- require 'plotly/util'
4
- require 'plotly/plot'
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "plotly"
metadata CHANGED
@@ -1,206 +1,64 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rbplotly
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
- - ash1day
8
- autorequire:
9
- bindir: exe
7
+ - Yoshihiro Ashida
8
+ bindir: bin
10
9
  cert_chain: []
11
- date: 2017-05-24 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
- name: faraday
13
+ name: json
15
14
  requirement: !ruby/object:Gem::Requirement
16
15
  requirements:
17
- - - "~>"
16
+ - - ">="
18
17
  - !ruby/object:Gem::Version
19
- version: '0.9'
18
+ version: '2.9'
20
19
  type: :runtime
21
20
  prerelease: false
22
21
  version_requirements: !ruby/object:Gem::Requirement
23
22
  requirements:
24
- - - "~>"
23
+ - - ">="
25
24
  - !ruby/object:Gem::Version
26
- version: '0.9'
27
- - !ruby/object:Gem::Dependency
28
- name: uuidtools
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '2.1'
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '2.1'
41
- - !ruby/object:Gem::Dependency
42
- name: launchy
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '2.4'
48
- type: :runtime
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '2.4'
55
- - !ruby/object:Gem::Dependency
56
- name: bundler
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: '1.12'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: '1.12'
69
- - !ruby/object:Gem::Dependency
70
- name: guard-rspec
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: '4.7'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: '4.7'
83
- - !ruby/object:Gem::Dependency
84
- name: guard-rubocop
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - "~>"
88
- - !ruby/object:Gem::Version
89
- version: '1.2'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - "~>"
95
- - !ruby/object:Gem::Version
96
- version: '1.2'
97
- - !ruby/object:Gem::Dependency
98
- name: rake
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - "~>"
102
- - !ruby/object:Gem::Version
103
- version: '11.2'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - "~>"
109
- - !ruby/object:Gem::Version
110
- version: '11.2'
111
- - !ruby/object:Gem::Dependency
112
- name: rspec
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - "~>"
116
- - !ruby/object:Gem::Version
117
- version: '3.5'
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - "~>"
123
- - !ruby/object:Gem::Version
124
- version: '3.5'
125
- - !ruby/object:Gem::Dependency
126
- name: yard
127
- requirement: !ruby/object:Gem::Requirement
128
- requirements:
129
- - - "~>"
130
- - !ruby/object:Gem::Version
131
- version: '0.9'
132
- type: :development
133
- prerelease: false
134
- version_requirements: !ruby/object:Gem::Requirement
135
- requirements:
136
- - - "~>"
137
- - !ruby/object:Gem::Version
138
- version: '0.9'
139
- - !ruby/object:Gem::Dependency
140
- name: codeclimate-test-reporter
141
- requirement: !ruby/object:Gem::Requirement
142
- requirements:
143
- - - "~>"
144
- - !ruby/object:Gem::Version
145
- version: '0.6'
146
- type: :development
147
- prerelease: false
148
- version_requirements: !ruby/object:Gem::Requirement
149
- requirements:
150
- - - "~>"
151
- - !ruby/object:Gem::Version
152
- version: '0.6'
153
- description: Rbplotly, a Ruby visualization library, allows you to create interactive
154
- plots.
25
+ version: '2.9'
26
+ description: Build Plotly.js figures with plain Ruby hashes, check every attribute
27
+ against the plot schema of the bundled plotly.js release, and write self-contained
28
+ HTML that works offline, in Rails views and in Jupyter (IRuby). No account or API
29
+ key needed.
155
30
  email:
156
31
  - y4ashida@gmail.com
157
32
  executables: []
158
33
  extensions: []
159
34
  extra_rdoc_files: []
160
35
  files:
161
- - ".gitignore"
162
- - ".rspec"
163
- - ".rubocop.yml"
164
- - ".travis.yml"
165
- - CODE_OF_CONDUCT.md
166
- - Gemfile
167
- - Guardfile
36
+ - CHANGELOG.md
168
37
  - LICENSE.txt
169
38
  - README.md
170
- - Rakefile
171
- - bin/console
172
- - bin/setup
173
- - docs/images/line_chart.png
174
- - examples/Bar Charts.ipynb
175
- - examples/Basic Usage.ipynb
176
- - examples/Histograms.ipynb
177
- - examples/Line charts.ipynb
178
- - examples/Pie Charts.ipynb
179
- - examples/Scatter Plots.ipynb
180
- - examples/heatmaps.ipynb
181
- - lib/plotly/axis.rb
182
- - lib/plotly/castable.rb
183
- - lib/plotly/client.rb
184
- - lib/plotly/data.rb
185
- - lib/plotly/exportable.rb
186
- - lib/plotly/layout.rb
187
- - lib/plotly/line.rb
188
- - lib/plotly/marker.rb
189
- - lib/plotly/offline/exportable.rb
190
- - lib/plotly/offline/html.rb
191
- - lib/plotly/offline/plotly.min.js
192
- - lib/plotly/offline/templates/body.erb
193
- - lib/plotly/offline/templates/plot.erb
39
+ - lib/plotly.rb
40
+ - lib/plotly/assets/plotly.min.js
41
+ - lib/plotly/attributes.rb
42
+ - lib/plotly/figure.rb
43
+ - lib/plotly/frames.rb
44
+ - lib/plotly/html.rb
194
45
  - lib/plotly/plot.rb
195
- - lib/plotly/util.rb
46
+ - lib/plotly/schema.rb
47
+ - lib/plotly/schema/plot-schema.json
48
+ - lib/plotly/serializer.rb
49
+ - lib/plotly/subplots.rb
196
50
  - lib/plotly/version.rb
197
51
  - lib/rbplotly.rb
198
- - rbplotly.gemspec
199
- homepage: https://github.com/y4ashida/rbplotly
52
+ homepage: https://github.com/ash1day/rbplotly
200
53
  licenses:
201
54
  - MIT
202
- metadata: {}
203
- post_install_message:
55
+ metadata:
56
+ homepage_uri: https://github.com/ash1day/rbplotly
57
+ source_code_uri: https://github.com/ash1day/rbplotly
58
+ changelog_uri: https://github.com/ash1day/rbplotly/blob/master/CHANGELOG.md
59
+ bug_tracker_uri: https://github.com/ash1day/rbplotly/issues
60
+ documentation_uri: https://rubydoc.info/gems/rbplotly
61
+ rubygems_mfa_required: 'true'
204
62
  rdoc_options: []
205
63
  require_paths:
206
64
  - lib
@@ -208,16 +66,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
208
66
  requirements:
209
67
  - - ">="
210
68
  - !ruby/object:Gem::Version
211
- version: '0'
69
+ version: '3.3'
212
70
  required_rubygems_version: !ruby/object:Gem::Requirement
213
71
  requirements:
214
72
  - - ">="
215
73
  - !ruby/object:Gem::Version
216
74
  version: '0'
217
75
  requirements: []
218
- rubyforge_project:
219
- rubygems_version: 2.5.2
220
- signing_key:
76
+ rubygems_version: 4.0.20
221
77
  specification_version: 4
222
- summary: a Ruby visualization library
78
+ summary: Interactive Plotly.js charts from Ruby, validated against the plotly.js schema
223
79
  test_files: []
data/.gitignore DELETED
@@ -1,11 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /Gemfile.lock
4
- /_yardoc/
5
- /coverage/
6
- /doc/
7
- /pkg/
8
- /spec/reports/
9
- /tmp/
10
-
11
- .ipynb_checkpoints
data/.rspec DELETED
@@ -1,2 +0,0 @@
1
- --format documentation
2
- --color
data/.rubocop.yml DELETED
@@ -1,22 +0,0 @@
1
- AllCops:
2
- TargetRubyVersion: 2.3
3
-
4
- Style/FrozenStringLiteralComment:
5
- Enabled: false
6
-
7
- LineLength:
8
- Max: 100
9
-
10
- MethodLength:
11
- Max: 15
12
-
13
- Documentation:
14
- Enabled: false
15
-
16
- ParameterLists:
17
- CountKeywordArgs: false
18
-
19
- RegexpLiteral:
20
- Exclude:
21
- - '**/*.gemspec'
22
- - '**/Guardfile'
data/.travis.yml DELETED
@@ -1,9 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 2.3.1
4
- script: bundle exec rake ci
5
- sudo: false
6
- cache: bundler
7
- addons:
8
- code_climate:
9
- repo_token: c30552ebdf8e631457b7dc321138e8d1455e36def696c453ba9428dc082f247f