highcharts-rails 3.0.1 → 3.0.1.5.pre1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.markdown +4 -0
- data/README.markdown +48 -0
- data/highcharts-rails.gemspec +1 -0
- data/lib/highcharts-rails.rb +1 -1
- data/lib/highcharts/export_endpoint.rb +122 -0
- data/lib/highcharts/version.rb +1 -1
- metadata +23 -5
- data.tar.gz.asc +0 -18
- metadata.gz.asc +0 -18
data/CHANGELOG.markdown
CHANGED
data/README.markdown
CHANGED
@@ -45,6 +45,54 @@ Or one of the themes
|
|
45
45
|
|
46
46
|
Other than that, refer to the [Highcharts documentation](http://highcharts.com/documentation/how-to-use)
|
47
47
|
|
48
|
+
## Export endpoint
|
49
|
+
|
50
|
+
This gem contains a Rack endpoint for converting the chart to a downloadable file.
|
51
|
+
It is not required by default, so to use it, `require
|
52
|
+
'highcharts/export_endpoint'`
|
53
|
+
|
54
|
+
The endpoint is basically a port of the [PHP version made available](https://github.com/highslide-software/highcharts.com/blob/master/exporting-server/php/php-batik/index.php).
|
55
|
+
It currently needs a lot of cleanup, but it is working fine for me. Your milage
|
56
|
+
may vary.
|
57
|
+
|
58
|
+
It uses [Apache Batik](http://xmlgraphics.apache.org/batik/) for the conversion, which must be
|
59
|
+
installed separately, as well as a Java Runtime Environment.
|
60
|
+
|
61
|
+
It expects to find a JRE in `/usr/bin/java`, and Batik in
|
62
|
+
`/usr/share/java/batik-rasterizer.jar`, but both paths are configurable.
|
63
|
+
|
64
|
+
Example usage in Rails:
|
65
|
+
|
66
|
+
# config/routes.rb
|
67
|
+
require 'highcharts/export_endpoint'
|
68
|
+
|
69
|
+
MyRailsApp::Application.routes.draw do
|
70
|
+
...
|
71
|
+
mount Highcharts::ExportEndpoint.new({
|
72
|
+
java_path: "/usr/bin/java",
|
73
|
+
batik: "/usr/share/java/batik-rasterizer.jar"
|
74
|
+
}), at: "highcharts-export"
|
75
|
+
...
|
76
|
+
end
|
77
|
+
|
78
|
+
# When rendering the chart
|
79
|
+
new Highcharts.Chart({
|
80
|
+
...
|
81
|
+
exporting: {
|
82
|
+
url: "/highcharts-export",
|
83
|
+
...
|
84
|
+
}
|
85
|
+
})
|
86
|
+
|
87
|
+
### Cocaine
|
88
|
+
|
89
|
+
The exporting endpoint uses [Cocaine](https://github.com/thoughtbot/cocaine) for
|
90
|
+
handling the command lines and arguments and so on.
|
91
|
+
|
92
|
+
I don't know a way to get optional dependencies in the gemspec, so for now
|
93
|
+
that gets added whether you want it or not. I'd like to get this fixed,
|
94
|
+
but would also like to avoid `begin; require 'cocaine'; rescue LoadError; ...; end` and similar hacks.
|
95
|
+
|
48
96
|
## Licensing
|
49
97
|
|
50
98
|
Highcharts, which makes up the majority of this gem, has [its own, separate licensing](http://highcharts.com/license).
|
data/highcharts-rails.gemspec
CHANGED
data/lib/highcharts-rails.rb
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
require 'highcharts/version'
|
2
|
-
require 'highcharts/rails'
|
2
|
+
require 'highcharts/rails'
|
@@ -0,0 +1,122 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'cocaine'
|
3
|
+
|
4
|
+
module Highcharts
|
5
|
+
class ExportEndpoint
|
6
|
+
class InsecureSVGError < ArgumentError; end
|
7
|
+
class MissingLibrary < RuntimeError; end
|
8
|
+
class FailedToGenerateChart < RuntimeError; end
|
9
|
+
class InvalidType < ArgumentError; end
|
10
|
+
|
11
|
+
attr_reader :output, :options
|
12
|
+
|
13
|
+
def initialize(options = {})
|
14
|
+
@options = default_options.merge(options)
|
15
|
+
end
|
16
|
+
|
17
|
+
def default_options
|
18
|
+
{
|
19
|
+
java_path: "/usr/bin/java",
|
20
|
+
batik: "/usr/share/java/batik-rasterizer.jar",
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
def call(env)
|
25
|
+
dup._call(env)
|
26
|
+
end
|
27
|
+
|
28
|
+
def _call(env)
|
29
|
+
with_rescues do
|
30
|
+
raise MissingLibrary.new("Could not find batik-rasterizer.jar in #{options[:batik].inspect}") unless File.exists?(options[:batik].to_s)
|
31
|
+
|
32
|
+
request = Rack::Request.new(env)
|
33
|
+
|
34
|
+
filename = request.params["filename"].to_s
|
35
|
+
filename = "chart" if filename.blank? || filename !~ /\A[A-Za-z0-9\-_ ]+\Z/
|
36
|
+
|
37
|
+
type = request.params["type"].to_s
|
38
|
+
width = request.params["width"].to_i
|
39
|
+
svg = request.params["svg"].to_s
|
40
|
+
|
41
|
+
raise InsecureSVGError.new if svg.index("<!ENTITY") || svg.index("<!DOCTYPE")
|
42
|
+
|
43
|
+
if type == "image/svg+xml"
|
44
|
+
# We were sent SVG from the client, so can just render that back
|
45
|
+
return [200, {
|
46
|
+
'Content-Disposition' => "attachment; filename=\"#{filename}.svg\"",
|
47
|
+
'Content-Type' => 'image/svg+xml'
|
48
|
+
}, [svg]]
|
49
|
+
end
|
50
|
+
|
51
|
+
width = width > 0 ? width.to_s : "600"
|
52
|
+
extension = case type
|
53
|
+
when "image/png" then "png"
|
54
|
+
when "image/jpeg" then "jpg"
|
55
|
+
when "application/pdf" then "pdf"
|
56
|
+
when "image/svg+xml" then "svg"
|
57
|
+
else raise InvalidType.new("#{type} is not a valid type.")
|
58
|
+
end
|
59
|
+
|
60
|
+
input = write_svg_to_file(svg)
|
61
|
+
@output = create_output_file(extension)
|
62
|
+
|
63
|
+
command.run(batik: options[:batik], outfile: output.path, type: type, width: width, infile: input.path)
|
64
|
+
input.close
|
65
|
+
content_length = output.size
|
66
|
+
output.rewind
|
67
|
+
|
68
|
+
raise FailedToGenerateChart.new("Nothing written to file") if !File.exists?(output.path) || content_length < 10
|
69
|
+
|
70
|
+
Rack::Response.new(self, 200, {
|
71
|
+
'Content-Disposition' => "attachment; filename=\"#{filename}.#{extension}\"",
|
72
|
+
'Content-Type' => type
|
73
|
+
}).finish
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Pass the block along to the output file, and
|
78
|
+
# make sure to close the file afterwards
|
79
|
+
def each(&block)
|
80
|
+
output.each(&block)
|
81
|
+
ensure
|
82
|
+
output.close
|
83
|
+
end
|
84
|
+
|
85
|
+
def command
|
86
|
+
Cocaine::CommandLine.new(options[:java_path], "-jar :batik -m :type -d :outfile -w :width :infile")
|
87
|
+
end
|
88
|
+
|
89
|
+
def write_svg_to_file(contents)
|
90
|
+
file = ::Tempfile.new(["highcharts-input", ".svg"], Dir.tmpdir, encoding: 'utf-8')
|
91
|
+
file.puts contents
|
92
|
+
file.flush
|
93
|
+
file
|
94
|
+
end
|
95
|
+
|
96
|
+
def create_output_file(extension)
|
97
|
+
file = ::Tempfile.new(["highcharts-chart", ".#{extension}"])
|
98
|
+
file.binmode
|
99
|
+
file
|
100
|
+
end
|
101
|
+
|
102
|
+
def with_rescues
|
103
|
+
yield
|
104
|
+
rescue Highcharts::ExportEndpoint::InsecureSVGError => e
|
105
|
+
[400, {'Content-Type' => 'text/plain'}, ["The posted SVG could contain code for a malicious attack"]]
|
106
|
+
rescue Highcharts::ExportEndpoint::InvalidType => e
|
107
|
+
[400, {'Content-Type' => 'text/plain'}, [e]]
|
108
|
+
rescue Cocaine::CommandNotFoundError => e
|
109
|
+
[503, {'Content-Type' => 'text/plain'}, ["Unable to find required binary. #{e}"]]
|
110
|
+
rescue Highcharts::ExportEndpoint::MissingLibrary => e
|
111
|
+
[503, {'Content-Type' => 'text/plain'}, ["Unable to find required library. #{e}"]]
|
112
|
+
rescue Highcharts::ExportEndpoint::FailedToGenerateChart => e
|
113
|
+
[500, {'Content-Type' => 'text/plain'}, ["Failed to generate chart. More details may be available in the server logs."]]
|
114
|
+
rescue => e
|
115
|
+
[500, {'Content-Type' => 'text/plain'}, ["Something went wrong. More details may be available in the server logs."]]
|
116
|
+
end
|
117
|
+
|
118
|
+
def error(code, message)
|
119
|
+
[code, {}, [message].flatten]
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
data/lib/highcharts/version.rb
CHANGED
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: highcharts-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
prerelease:
|
5
|
-
version: 3.0.1
|
4
|
+
prerelease: 8
|
5
|
+
version: 3.0.1.5.pre1
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Per Christian B. Viken
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-04-
|
12
|
+
date: 2013-04-19 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: railties
|
@@ -27,6 +27,22 @@ dependencies:
|
|
27
27
|
- - ! '>='
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: '3.1'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: cocaine
|
32
|
+
type: :runtime
|
33
|
+
requirement: !ruby/object:Gem::Requirement
|
34
|
+
none: false
|
35
|
+
requirements:
|
36
|
+
- - ~>
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: 0.4.0
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 0.4.0
|
30
46
|
- !ruby/object:Gem::Dependency
|
31
47
|
name: bundler
|
32
48
|
type: :development
|
@@ -91,6 +107,7 @@ files:
|
|
91
107
|
- app/assets/javascripts/highcharts/themes/skies.js
|
92
108
|
- highcharts-rails.gemspec
|
93
109
|
- lib/highcharts-rails.rb
|
110
|
+
- lib/highcharts/export_endpoint.rb
|
94
111
|
- lib/highcharts/rails.rb
|
95
112
|
- lib/highcharts/version.rb
|
96
113
|
homepage: http://northblue.org/
|
@@ -108,9 +125,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
108
125
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
109
126
|
none: false
|
110
127
|
requirements:
|
111
|
-
- - ! '
|
128
|
+
- - ! '>'
|
112
129
|
- !ruby/object:Gem::Version
|
113
|
-
version:
|
130
|
+
version: 1.3.1
|
114
131
|
requirements: []
|
115
132
|
rubyforge_project:
|
116
133
|
rubygems_version: 1.8.24
|
@@ -118,3 +135,4 @@ signing_key:
|
|
118
135
|
specification_version: 3
|
119
136
|
summary: Gem for easily adding Highcharts to the Rails Asset Pipeline
|
120
137
|
test_files: []
|
138
|
+
has_rdoc:
|
data.tar.gz.asc
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
-----BEGIN PGP SIGNATURE-----
|
2
|
-
Version: GnuPG/MacGPG2 v2.0.19 (Darwin)
|
3
|
-
Comment: GPGTools - http://gpgtools.org
|
4
|
-
|
5
|
-
iQIcBAABAgAGBQJRZCX4AAoJEH1ncb0Txu7XWUgQAKSwMYAj6ECNovM5FQnW9Xrs
|
6
|
-
84xcCzwhur/YD5/jOVxl85tTVmboBRdVPp53CmsuquGYUMRrrXRobt6C6/hMp4DP
|
7
|
-
imZ72AL1ZjYjFPCjHXuJzVXsiwGKLE7SdhGo01l3+69rhGwurpA3fZ9d1DaO+YZ6
|
8
|
-
BlwHypnXlQGOPapB7Eh2V/U5UbZi3V1kLTlUaJyUu914p99Jo6MutHobM7aShMOx
|
9
|
-
hdqn+ZqN0ha2ourKFk+wJKWTMKe4jvlp9SDrOLe9JY+AJ9zfCns+QFwFJQaC6+VE
|
10
|
-
DlxQVt33q2nl+W7DdQr23kBM9/Vr9tQzNPE4E17NvGGZBwTZGxPSwPVzoO1ajRVH
|
11
|
-
MwzbcKrqo1AkRDY5th1Hf2WAyruQ62DlbHF/5luJo1ezsuakus74/JWIo36BXKdp
|
12
|
-
R20yR4hnQflxGj9BwOUZ5oroG4+PvIBHEfy9no7R600u5Q/RzCj+C3MCekYTMyKV
|
13
|
-
KurzDyFfanNU1RNVkV2rJAAB2373cCZRiORqi7HNfdjkzzJiuFCTIWNkEo2eLPx4
|
14
|
-
KlCZL5czNj1fgiEZclMGqv7Le5RXR3SuQXzxTw/cpEbvy5Zwm1zUGWankUQb+TEg
|
15
|
-
7hP/wQD5E8zJ/ZYbYjXCnS2K8e59+EOc5DcGpaPT9ELSmaCDlG3AvNnKuFS3g+nj
|
16
|
-
pm1NAKtYl8Y62Yf35hba
|
17
|
-
=qJvF
|
18
|
-
-----END PGP SIGNATURE-----
|
metadata.gz.asc
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
-----BEGIN PGP SIGNATURE-----
|
2
|
-
Version: GnuPG/MacGPG2 v2.0.19 (Darwin)
|
3
|
-
Comment: GPGTools - http://gpgtools.org
|
4
|
-
|
5
|
-
iQIbBAABAgAGBQJRZCX4AAoJEH1ncb0Txu7X/t4P9R5ENkevewpnG4BmYF2THRJd
|
6
|
-
bws9bcN4bPeSYpceQBphAnFEVQfL+QAXzTweHHw5nk/mGg1iPl18ySyWWeWdSq+G
|
7
|
-
bbjIAqcG9IdeX/ItzzWXn47WvXhjsu7s6LZ3vP57Y7q0+AcHW45Tl90p1XYSFI3D
|
8
|
-
1Cx1lh6ljZ7JtsNe8j3lnxHq/gL29RA+f4u+k8u+jdas69I+dpcc5EiuI+9C2AnB
|
9
|
-
usTAafb8Q7lVwsiv9Mkgufai5c3J9LkSZOjLF8GhoXSVE/xybAFpFs4SzyoGKm6K
|
10
|
-
C/xXtZV+78/sv5WUm1UK//T/9LXO0jebYiE5/WZgJZDnt/zDVJDYU5Nmsr9IF1ty
|
11
|
-
QYRHUO3iMZODpDyeRxKDEL1DMYoKrZJbvZqbJx+0FmYSfvxqcyX0cKoIFYOLhZUo
|
12
|
-
rxWKoEw3otoWiJhKJPC6A+CkYS3NxOjHjixhRs6T59Dxo5Hb5dYO9cF823feCIGU
|
13
|
-
ge/FlB4wBTJeFrSSMTjl/ABU5Vrdfx2/Ng5e/nyAwFaki8p4n8CRNnfYvsJ8SvQC
|
14
|
-
8jAspjcyeiXzQx27ujgny45NTYNMkfrl01OLHsRjVaXnTw97z8+96QQaCV/5M0tA
|
15
|
-
ZZtWxDI2BTWXIkzBp0BzyAq1utDiS++CE/p3nEhlDGRMwj49iAg3JD3mfS0/OfmB
|
16
|
-
cHbhD6RW3WPUEGUKW4M=
|
17
|
-
=LkjG
|
18
|
-
-----END PGP SIGNATURE-----
|