inkplot 0.1.0
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.
- checksums.yaml +7 -0
- data/.rubocop.yml +35 -0
- data/CHANGELOG.md +5 -0
- data/LICENSE.txt +21 -0
- data/README.md +72 -0
- data/Rakefile +15 -0
- data/bench/inkplot.rb +12 -0
- data/examples/gallery/01-line.svg +1 -0
- data/examples/gallery/02-line-gaps.svg +1 -0
- data/examples/gallery/03-series.svg +1 -0
- data/examples/gallery/04-scatter.svg +1 -0
- data/examples/gallery/05-bars.svg +1 -0
- data/examples/gallery/06-horizontal-bars.svg +1 -0
- data/examples/gallery/07-grouped-bars.svg +1 -0
- data/examples/gallery/08-stacked-bars.svg +1 -0
- data/examples/gallery/10-area.svg +1 -0
- data/examples/gallery/11-step.svg +1 -0
- data/examples/gallery/README.md +11 -0
- data/examples/gallery.rb +49 -0
- data/lib/inkplot/core.rb +624 -0
- data/lib/inkplot/renderers/svg.rb +75 -0
- data/lib/inkplot/version.rb +5 -0
- data/lib/inkplot.rb +71 -0
- data/sig/inkplot.rbs +36 -0
- metadata +122 -0
data/lib/inkplot.rb
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "inkplot/version"
|
|
4
|
+
require_relative "inkplot/core"
|
|
5
|
+
require_relative "inkplot/renderers/svg"
|
|
6
|
+
|
|
7
|
+
module Inkplot
|
|
8
|
+
class Error < StandardError; end
|
|
9
|
+
|
|
10
|
+
class Config
|
|
11
|
+
attr_accessor :font
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
Series = Struct.new(:type, :points, :label, :color, :options, keyword_init: true)
|
|
15
|
+
Scene = Struct.new(:width, :height, :background, :clip, :marks, :elements, keyword_init: true)
|
|
16
|
+
|
|
17
|
+
class << self
|
|
18
|
+
def config = @config ||= Config.new
|
|
19
|
+
|
|
20
|
+
def plot(width: 640, height: 360, theme: :light, **)
|
|
21
|
+
builder = Builder.new(width: width, height: height, theme: theme, **)
|
|
22
|
+
yield builder if block_given?
|
|
23
|
+
Chart.new(builder)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def line(data, values = nil, x: nil, y: nil, color: nil, title: nil, x_label: nil, y_label: nil, **)
|
|
27
|
+
quick(:line, data, values, x:, y:, color:, title:, x_label:, y_label:, **)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def scatter(data, values = nil, x: nil, y: nil, size: nil, color: nil, title: nil, x_label: nil, y_label: nil, **)
|
|
31
|
+
quick(:scatter, data, values, x:, y:, size:, color:, title:, x_label:, y_label:, **)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def bar(data, horizontal: false, title: nil, x_label: nil, y_label: nil, **options)
|
|
35
|
+
chart_options, mark_options = options.partition { |key, _| %i[width height theme].include?(key) }.map(&:to_h)
|
|
36
|
+
builder = Builder.new(**chart_options, title:, x_label:, y_label:)
|
|
37
|
+
if horizontal
|
|
38
|
+
builder.bar(data, horizontal: true, **mark_options)
|
|
39
|
+
else
|
|
40
|
+
builder.bar(data, **mark_options)
|
|
41
|
+
end
|
|
42
|
+
Chart.new(builder)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def sparkline(values)
|
|
46
|
+
values = values.filter_map { |value| Data.number(value) }
|
|
47
|
+
return "" if values.empty?
|
|
48
|
+
|
|
49
|
+
low, high = values.minmax
|
|
50
|
+
glyphs = "▁▂▃▄▅▆▇█"
|
|
51
|
+
return glyphs[3] * values.length if low == high
|
|
52
|
+
|
|
53
|
+
values.map { |value| glyphs[((value - low) / (high - low) * 7).round] }.join
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
private
|
|
57
|
+
|
|
58
|
+
def quick(type, data, values = nil, x:, y:, size: nil, color: nil, title: nil, x_label: nil, y_label: nil, **options)
|
|
59
|
+
chart_options, mark_options = options.partition { |key, _| %i[width height theme].include?(key) }.map(&:to_h)
|
|
60
|
+
builder = Builder.new(**chart_options, title:, x_label:, y_label:)
|
|
61
|
+
if color && Data.records?(data)
|
|
62
|
+
Data.rows(data, x:, y:, size:, group: color).group_by { |point| point[:group] }.each do |group, points|
|
|
63
|
+
builder.add(type, points, label: group.to_s, **mark_options)
|
|
64
|
+
end
|
|
65
|
+
else
|
|
66
|
+
builder.add(type, Data.points(data, values, x:, y:, size:), **mark_options)
|
|
67
|
+
end
|
|
68
|
+
Chart.new(builder)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
data/sig/inkplot.rbs
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
module Inkplot
|
|
2
|
+
VERSION: String
|
|
3
|
+
|
|
4
|
+
class Config
|
|
5
|
+
attr_accessor font: String?
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
class Builder
|
|
9
|
+
def title: (String value) -> String
|
|
10
|
+
def x_axis: (?label: String?, ?type: Symbol?, ?scale: Symbol?, ?min: untyped, ?max: untyped, ?order: Array[untyped]?) -> Hash[Symbol, untyped]
|
|
11
|
+
def y_axis: (?label: String?, ?type: Symbol?, ?scale: Symbol?, ?min: untyped, ?max: untyped) -> Hash[Symbol, untyped]
|
|
12
|
+
def legend: (?position: Symbol) -> Hash[Symbol, Symbol]
|
|
13
|
+
def line: (untyped x, ?untyped y, ?label: String?, ?color: String?, ?dash: bool, ?gaps: Symbol, **untyped options) -> Builder
|
|
14
|
+
def scatter: (untyped x, ?untyped y, ?label: String?, ?color: String?, ?size: untyped, **untyped options) -> Builder
|
|
15
|
+
def area: (untyped x, ?untyped y, ?label: String?, ?color: String?, **untyped options) -> Builder
|
|
16
|
+
def step: (untyped x, ?untyped y, ?label: String?, ?color: String?, **untyped options) -> Builder
|
|
17
|
+
def bar: (untyped categories, ?untyped values, ?label: String?, ?color: String?, ?horizontal: bool, ?stacked: bool, **untyped options) -> Builder
|
|
18
|
+
def hline: (Numeric value, ?label: String?, ?color: String?, ?dash: bool) -> Array[Hash[Symbol, untyped]]
|
|
19
|
+
def vline: (untyped value, ?label: String?, ?color: String?, ?dash: bool) -> Array[Hash[Symbol, untyped]]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class Chart
|
|
23
|
+
attr_reader builder: Builder
|
|
24
|
+
attr_reader width: Integer
|
|
25
|
+
attr_reader height: Integer
|
|
26
|
+
def to_svg: (?width: Integer, ?height: Integer) -> String
|
|
27
|
+
def save: (String | _Path path, ?width: Integer, ?height: Integer) -> String | _Path
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def self.config: () -> Config
|
|
31
|
+
def self.plot: (?width: Integer, ?height: Integer, ?theme: Symbol, **untyped options) { (Builder) -> void } -> Chart
|
|
32
|
+
def self.line: (untyped data, ?untyped values, ?x: untyped, ?y: untyped, ?color: untyped, ?title: String?, ?x_label: String?, ?y_label: String?, **untyped options) -> Chart
|
|
33
|
+
def self.scatter: (untyped data, ?untyped values, ?x: untyped, ?y: untyped, ?size: untyped, ?color: untyped, ?title: String?, ?x_label: String?, ?y_label: String?, **untyped options) -> Chart
|
|
34
|
+
def self.bar: (untyped data, ?horizontal: bool, ?title: String?, ?x_label: String?, ?y_label: String?, **untyped options) -> Chart
|
|
35
|
+
def self.sparkline: (Array[untyped] values) -> String
|
|
36
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: inkplot
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Yudai Takada
|
|
8
|
+
bindir: exe
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: rake
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '13.0'
|
|
19
|
+
type: :development
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '13.0'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: rbs
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '3.0'
|
|
33
|
+
type: :development
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '3.0'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: rspec
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - "~>"
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '3.0'
|
|
47
|
+
type: :development
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - "~>"
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '3.0'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: rubocop
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - "~>"
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '1.0'
|
|
61
|
+
type: :development
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - "~>"
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '1.0'
|
|
68
|
+
description: Build line, bar, scatter, and other charts as standalone SVG.
|
|
69
|
+
email:
|
|
70
|
+
- t.yudai92@gmail.com
|
|
71
|
+
executables: []
|
|
72
|
+
extensions: []
|
|
73
|
+
extra_rdoc_files: []
|
|
74
|
+
files:
|
|
75
|
+
- ".rubocop.yml"
|
|
76
|
+
- CHANGELOG.md
|
|
77
|
+
- LICENSE.txt
|
|
78
|
+
- README.md
|
|
79
|
+
- Rakefile
|
|
80
|
+
- bench/inkplot.rb
|
|
81
|
+
- examples/gallery.rb
|
|
82
|
+
- examples/gallery/01-line.svg
|
|
83
|
+
- examples/gallery/02-line-gaps.svg
|
|
84
|
+
- examples/gallery/03-series.svg
|
|
85
|
+
- examples/gallery/04-scatter.svg
|
|
86
|
+
- examples/gallery/05-bars.svg
|
|
87
|
+
- examples/gallery/06-horizontal-bars.svg
|
|
88
|
+
- examples/gallery/07-grouped-bars.svg
|
|
89
|
+
- examples/gallery/08-stacked-bars.svg
|
|
90
|
+
- examples/gallery/10-area.svg
|
|
91
|
+
- examples/gallery/11-step.svg
|
|
92
|
+
- examples/gallery/README.md
|
|
93
|
+
- lib/inkplot.rb
|
|
94
|
+
- lib/inkplot/core.rb
|
|
95
|
+
- lib/inkplot/renderers/svg.rb
|
|
96
|
+
- lib/inkplot/version.rb
|
|
97
|
+
- sig/inkplot.rbs
|
|
98
|
+
homepage: https://github.com/rbgfx/inkplot
|
|
99
|
+
licenses:
|
|
100
|
+
- MIT
|
|
101
|
+
metadata:
|
|
102
|
+
homepage_uri: https://github.com/rbgfx/inkplot
|
|
103
|
+
source_code_uri: https://github.com/rbgfx/inkplot/tree/main
|
|
104
|
+
rubygems_mfa_required: 'true'
|
|
105
|
+
rdoc_options: []
|
|
106
|
+
require_paths:
|
|
107
|
+
- lib
|
|
108
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
109
|
+
requirements:
|
|
110
|
+
- - ">="
|
|
111
|
+
- !ruby/object:Gem::Version
|
|
112
|
+
version: 3.2.0
|
|
113
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
114
|
+
requirements:
|
|
115
|
+
- - ">="
|
|
116
|
+
- !ruby/object:Gem::Version
|
|
117
|
+
version: '0'
|
|
118
|
+
requirements: []
|
|
119
|
+
rubygems_version: 4.0.16
|
|
120
|
+
specification_version: 4
|
|
121
|
+
summary: SVG charts for Ruby
|
|
122
|
+
test_files: []
|