grapht 0.1.6 → 0.1.7
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 +4 -4
- data/.travis.yml +22 -0
- data/Gemfile +2 -6
- data/README.md +104 -86
- data/Rakefile +6 -0
- data/grapht.gemspec +1 -1
- data/lib/grapht/shell.rb +3 -1
- data/lib/grapht/type.rb +4 -1
- data/lib/grapht/version.rb +1 -1
- data/script/grapht.coffee +14 -1
- data/spec/lib/grapht/shell_spec.rb +23 -1
- metadata +9 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1c81c4cd2f0ae2bead5fae5316a8f4143a81a5f7
|
4
|
+
data.tar.gz: bbfcabd60418b98db230be8ee8a2b4d374fc1359
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 746748c55ed22100d08010c4ce3c48fe1339a2af7d03d57ba7ce9bacdc8290be16ab56d9d7bf12b3f618ab39ef6df98b48f844ed5cbc160fc91fe836f0010afb
|
7
|
+
data.tar.gz: 1a864c3901bf0d638db817c969ba69e437e979b9398cf3342d63a60301cb4dd56020bf384b6d46a5965bf7366a1620221d860de999846bee8071f3a2c5842743
|
data/.travis.yml
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
language: ruby
|
2
|
+
cache: bundler
|
3
|
+
rvm:
|
4
|
+
- 1.9.2
|
5
|
+
- 1.9.3
|
6
|
+
- 2.0.0
|
7
|
+
- 2.1.0
|
8
|
+
- 2.1.1
|
9
|
+
- ruby-head
|
10
|
+
- rbx-2
|
11
|
+
matrix:
|
12
|
+
include:
|
13
|
+
- rvm: jruby-18mode
|
14
|
+
env: JRUBY_OPTS="$JRUBY_OPTS --debug"
|
15
|
+
- rvm: jruby-19mode
|
16
|
+
env: JRUBY_OPTS="$JRUBY_OPTS --debug"
|
17
|
+
- rvm: jruby-head
|
18
|
+
env: JRUBY_OPTS="$JRUBY_OPTS --debug"
|
19
|
+
allow_failures:
|
20
|
+
- rvm: ruby-head
|
21
|
+
- rvm: jruby-head
|
22
|
+
fast_finish: true
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -2,6 +2,9 @@
|
|
2
2
|
|
3
3
|
# Grapht
|
4
4
|
|
5
|
+
[](https://travis-ci.org/trade-informatics/grapht)
|
6
|
+
[](https://rubygems.org/gems/grapht)
|
7
|
+
|
5
8
|
Grapht is a server-side graphing library built on [PhantomJS](https://github.com/ariya/phantomjs/wiki)
|
6
9
|
and utilizing [D3.js](http://d3js.org/). Grapht provides a CLI for simple Bash scripting.
|
7
10
|
It also profides a light-weight [Ruby](https://www.ruby-lang.org/en/)
|
@@ -65,81 +68,87 @@ Grapht provides a CLI, accessed using the `bin/grapht` command. The basic invoc
|
|
65
68
|
requires one argument specifying the desired graph type, and a JSON string provided
|
66
69
|
via `STDIN`. For example, if we want a **horizontal bar graph**:
|
67
70
|
|
68
|
-
|
71
|
+
```bash
|
72
|
+
bin/grapht bar-horizontal < ~/my-data.json
|
73
|
+
```
|
69
74
|
|
70
75
|
The result will be a string of **svg** markup:
|
71
76
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
77
|
+
```html
|
78
|
+
<svg width="200" height="200">
|
79
|
+
<rect class="bar" x="0" y="13" width="0" height="50"></rect>
|
80
|
+
<rect class="bar" x="0" y="75" width="200" height="50"></rect>
|
81
|
+
<rect class="bar" x="0" y="137" width="150" height="50"></rect>
|
82
|
+
<g class="x axis" transform="translate(0,200)">
|
83
|
+
<g class="tick" style="opacity: 1; " transform="translate(0,0)">
|
84
|
+
<line y2="-200" x2="0"></line>
|
85
|
+
<text y="3" x="0" dy=".71em" style="text-anchor: middle; ">20</text>
|
86
|
+
</g>
|
87
|
+
<g class="tick" style="opacity: 1; " transform="translate(20,0)">
|
88
|
+
<line y2="-200" x2="0"></line>
|
89
|
+
<text y="3" x="0" dy=".71em" style="text-anchor: middle; ">22</text>
|
90
|
+
</g>
|
91
|
+
<g class="tick" style="opacity: 1; " transform="translate(40,0)">
|
92
|
+
<line y2="-200" x2="0"></line>
|
93
|
+
<text y="3" x="0" dy=".71em" style="text-anchor: middle; ">24</text>
|
94
|
+
</g>
|
95
|
+
<g class="tick" style="opacity: 1; " transform="translate(60.00000000000001,0)">
|
96
|
+
<line y2="-200" x2="0"></line>
|
97
|
+
<text y="3" x="0" dy=".71em" style="text-anchor: middle; ">26</text>
|
98
|
+
</g>
|
99
|
+
<g class="tick" style="opacity: 1; " transform="translate(80,0)">
|
100
|
+
<line y2="-200" x2="0"></line>
|
101
|
+
<text y="3" x="0" dy=".71em" style="text-anchor: middle; ">28</text>
|
102
|
+
</g>
|
103
|
+
<g class="tick" style="opacity: 1; " transform="translate(100,0)">
|
104
|
+
<line y2="-200" x2="0"></line>
|
105
|
+
<text y="3" x="0" dy=".71em" style="text-anchor: middle; ">30</text>
|
106
|
+
</g>
|
107
|
+
<g class="tick" style="opacity: 1; " transform="translate(120.00000000000001,0)">
|
108
|
+
<line y2="-200" x2="0"></line>
|
109
|
+
<text y="3" x="0" dy=".71em" style="text-anchor: middle; ">32</text>
|
110
|
+
</g>
|
111
|
+
<g class="tick" style="opacity: 1; " transform="translate(140,0)">
|
112
|
+
<line y2="-200" x2="0"></line>
|
113
|
+
<text y="3" x="0" dy=".71em" style="text-anchor: middle; ">34</text>
|
114
|
+
</g>
|
115
|
+
<g class="tick" style="opacity: 1; " transform="translate(160,0)">
|
116
|
+
<line y2="-200" x2="0"></line>
|
117
|
+
<text y="3" x="0" dy=".71em" style="text-anchor: middle; ">36</text>
|
118
|
+
</g>
|
119
|
+
<g class="tick" style="opacity: 1; " transform="translate(180,0)">
|
120
|
+
<line y2="-200" x2="0"></line>
|
121
|
+
<text y="3" x="0" dy=".71em" style="text-anchor: middle; ">38</text>
|
122
|
+
</g>
|
123
|
+
<g class="tick" style="opacity: 1; " transform="translate(200,0)">
|
124
|
+
<line y2="-200" x2="0"></line>
|
125
|
+
<text y="3" x="0" dy=".71em" style="text-anchor: middle; ">40</text>
|
126
|
+
</g>
|
127
|
+
<path class="domain" d="M0,-200V0H200V-200"></path>
|
128
|
+
</g>
|
129
|
+
<g class="y axis">
|
130
|
+
<g class="tick" style="opacity: 1; " transform="translate(0,38)">
|
131
|
+
<line x2="6" y2="0"></line>
|
132
|
+
<text x="9" y="0" dy=".32em" style="text-anchor: start; ">foo</text>
|
133
|
+
</g>
|
134
|
+
<g class="tick" style="opacity: 1; " transform="translate(0,100)">
|
135
|
+
<line x2="6" y2="0"></line>
|
136
|
+
<text x="9" y="0" dy=".32em" style="text-anchor: start; ">bar</text>
|
137
|
+
</g>
|
138
|
+
<g class="tick" style="opacity: 1; " transform="translate(0,162)">
|
139
|
+
<line x2="6" y2="0"></line>
|
140
|
+
<text x="9" y="0" dy=".32em" style="text-anchor: start; ">baz</text>
|
141
|
+
</g>
|
142
|
+
<path class="domain" d="M6,0H0V200H6"></path>
|
143
|
+
</g>
|
144
|
+
</svg>
|
145
|
+
```
|
139
146
|
|
140
147
|
### Usage
|
141
148
|
|
142
|
-
|
149
|
+
```bash
|
150
|
+
bin/grapht GRAPH_TYPE [options] < JSON_INPUT
|
151
|
+
```
|
143
152
|
|
144
153
|
### Options
|
145
154
|
|
@@ -167,9 +176,11 @@ Currently supported flags:
|
|
167
176
|
To generate the same **horizontal bar graph** generated in the CLI
|
168
177
|
section--using the Ruby API--we can do the following:
|
169
178
|
|
170
|
-
|
171
|
-
|
172
|
-
|
179
|
+
```ruby
|
180
|
+
json = "[{ \"name\": \"foo\", \"value\": 20 },{ \"name\": \"bar\", \"value\": 40 },{ \"name\": \"baz\", \"value\": 35 }]"
|
181
|
+
type = Grapht::Type::BAR_HORIZONTAL
|
182
|
+
graph = Grapht::Shell.exec type, json
|
183
|
+
```
|
173
184
|
|
174
185
|
## Supported Graphs
|
175
186
|
|
@@ -191,8 +202,10 @@ For example, if we have our custom definitions stored in
|
|
191
202
|
`~/Development/my_project/my_graph_defs`, we set our environment variable to this
|
192
203
|
path:
|
193
204
|
|
194
|
-
|
195
|
-
|
205
|
+
```bash
|
206
|
+
export EXT_GRAPHT_DEFINITIONS_HOME=~/Development/my_project/my_graph_defs
|
207
|
+
bin/grapht my-scatterplot < ~/my-data.json
|
208
|
+
```
|
196
209
|
|
197
210
|
In the example above, we supply the name of our new graph definition
|
198
211
|
(`my-scatterplot`) to the Grapht CLI. Grapht will first look in
|
@@ -209,17 +222,19 @@ All graph definitions must comply with a short set of rules:
|
|
209
222
|
|
210
223
|
Here's an example of a valid graph definition:
|
211
224
|
|
212
|
-
|
213
|
-
|
214
|
-
|
225
|
+
```javascript
|
226
|
+
function(data) { // <- our wrapper fuction
|
227
|
+
var width = 200,
|
228
|
+
height = 200;
|
215
229
|
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
230
|
+
// our single root node added to document.body
|
231
|
+
var svg = d3.select("body").append("svg")
|
232
|
+
.attr("width", width)
|
233
|
+
.attr("height", height);
|
220
234
|
|
221
|
-
|
222
|
-
|
235
|
+
// a bunch of D3 operations on svg...
|
236
|
+
}
|
237
|
+
```
|
223
238
|
|
224
239
|
## Error Handling
|
225
240
|
|
@@ -245,11 +260,14 @@ While Rails integration is not scripted by the Grapht library, it is quite
|
|
245
260
|
simple to integrate. The following steps are all that is required for integration:
|
246
261
|
|
247
262
|
- Add the following to your `Gemfile`:
|
248
|
-
|
263
|
+
```ruby
|
264
|
+
gem 'grapht'
|
265
|
+
```
|
249
266
|
- In the Rails `app` directory, create a directory named `graph-definitions`
|
250
267
|
- Create the file `config/initializers/grapht.rb`. In the file add the following:
|
251
|
-
|
252
|
-
|
268
|
+
```ruby
|
269
|
+
ENV['EXT_GRAPHT_DEFINITIONS_HOME'] = Rails.root.join('app/graph-definitions')
|
270
|
+
```
|
253
271
|
- Place all user-defined graph definitions in the `app/graph-definitions`
|
254
272
|
|
255
273
|
## Contributing
|
data/Rakefile
CHANGED
data/grapht.gemspec
CHANGED
@@ -19,6 +19,6 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
21
|
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
22
23
|
spec.add_development_dependency "rake"
|
23
|
-
spec.add_development_dependency "rspec"
|
24
24
|
end
|
data/lib/grapht/shell.rb
CHANGED
@@ -10,7 +10,9 @@ module Grapht
|
|
10
10
|
def self.exec(type, json_data, options={})
|
11
11
|
options = *options.select { |k,v| ALLOWED_OPTIONS.include? k }.flatten
|
12
12
|
|
13
|
-
out, err, status =
|
13
|
+
out, err, status =
|
14
|
+
Open3.capture3 CMD, type, *options, stdin_data: json_data, binmode: true
|
15
|
+
|
14
16
|
raise Grapht::Shell::Error, err unless status.success?
|
15
17
|
out
|
16
18
|
end
|
data/lib/grapht/type.rb
CHANGED
data/lib/grapht/version.rb
CHANGED
data/script/grapht.coffee
CHANGED
@@ -11,6 +11,7 @@ defsPath = "#{scriptPath}../lib/graph-definitions/"
|
|
11
11
|
userDefsPath = system.env['EXT_GRAPHT_DEFINITIONS_HOME']
|
12
12
|
dependencies = ['d3.min.js', 'json2.js']
|
13
13
|
niceDirPathRX = /\/$|$/
|
14
|
+
naughtyPathRX = /(?:\.{1,2}\/)+/
|
14
15
|
|
15
16
|
# -----------------------------------------------------------------------------
|
16
17
|
# Helper Functions
|
@@ -28,10 +29,20 @@ fns =
|
|
28
29
|
|
29
30
|
phantom.exit(1)
|
30
31
|
|
32
|
+
# Scrubs-out any leading '/' characters from the type, and raises an error
|
33
|
+
# if any naughtier path manipulation is detected.
|
34
|
+
sanitizeType: (type) ->
|
35
|
+
if naughtyPathRX.test(type)
|
36
|
+
@logError "Naughty! There will be no backing out of the definition directory!"
|
37
|
+
|
38
|
+
type.replace(/^\/+/, '')
|
39
|
+
|
31
40
|
# Searchs for a valid graph definition in the supplied definition paths. If
|
32
41
|
# no definition is found, we log an error to STDERR and exit with an exitcode
|
33
42
|
# of 1.
|
34
43
|
findDef: (type, defPaths...) ->
|
44
|
+
type = @sanitizeType(type)
|
45
|
+
|
35
46
|
for dir in defPaths when dir?
|
36
47
|
dir = dir.replace(niceDirPathRX, '/')
|
37
48
|
path = "#{dir}#{type}.js"
|
@@ -84,7 +95,9 @@ fns =
|
|
84
95
|
# Configure the page context.
|
85
96
|
page.libraryPath = vendorPath
|
86
97
|
page.onError = fns.logError
|
87
|
-
|
98
|
+
|
99
|
+
dependencies.forEach (dp) ->
|
100
|
+
page.injectJs(dp) || fns.logError "could not load #{dp}!"
|
88
101
|
|
89
102
|
# load and evaluate the graph definition within the context of the JSON, supplied
|
90
103
|
# via STDIN.
|
@@ -23,11 +23,33 @@ describe Grapht::Shell do
|
|
23
23
|
context 'when given an unknown type' do
|
24
24
|
let(:type) { 'some-invalid-graph-type' }
|
25
25
|
|
26
|
-
it "should raise a Grapht::Shell
|
26
|
+
it "should raise a Grapht::Shell::Error" do
|
27
27
|
expect { subject }.to raise_error(Grapht::Shell::Error, /No graph definition could be found/)
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
+
context 'when a known type is provided with a leading forward-slash' do
|
32
|
+
let(:type) { "/#{Grapht::Type::BAR_HORIZONTAL}" }
|
33
|
+
it { should match(/^<svg/) }
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'when a naughty types are provided' do
|
37
|
+
[ "../buck-wild/corn-dogs",
|
38
|
+
"../../born-wild/chicken-skin",
|
39
|
+
"innocent-path/../../rootpath"
|
40
|
+
].each do |path|
|
41
|
+
context "for path: '#{path}'" do
|
42
|
+
let(:type) { path }
|
43
|
+
|
44
|
+
it 'should raise a Grapht::Shell::Error' do
|
45
|
+
expect { subject }.to raise_error(
|
46
|
+
Grapht::Shell::Error,
|
47
|
+
/Naughty! There will be no backing out of the definition directory!/)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
31
53
|
context 'when well-formed data is provided' do
|
32
54
|
it { should match(/^<svg/) }
|
33
55
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: grapht
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tim Lowrimore
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-08-
|
11
|
+
date: 2014-08-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -25,21 +25,21 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.3'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: rspec
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ~>
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '0'
|
33
|
+
version: '3.0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ~>
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '0'
|
40
|
+
version: '3.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: rake
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - '>='
|
@@ -64,8 +64,8 @@ extra_rdoc_files: []
|
|
64
64
|
files:
|
65
65
|
- .gitignore
|
66
66
|
- .rspec
|
67
|
+
- .travis.yml
|
67
68
|
- Gemfile
|
68
|
-
- Gemfile.lock
|
69
69
|
- LICENSE.txt
|
70
70
|
- README.md
|
71
71
|
- Rakefile
|