sparklines 0.4.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +7 -0
- data/Manifest.txt +7 -0
- data/Rakefile +17 -0
- data/lib/sparklines.rb +89 -19
- data/test/{all_test.rb → test_all.rb} +20 -1
- metadata +25 -15
- data/MIT-LICENSE +0 -21
- data/rakefile +0 -213
data/CHANGELOG
CHANGED
data/Manifest.txt
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
|
2
|
+
require 'rubygems'
|
3
|
+
require 'hoe'
|
4
|
+
$:.unshift(File.dirname(__FILE__) + "/lib")
|
5
|
+
require 'sparklines'
|
6
|
+
|
7
|
+
Hoe.new('Sparklines', Sparklines::VERSION) do |p|
|
8
|
+
p.name = "sparklines"
|
9
|
+
p.author = "Geoffrey Grosenbach"
|
10
|
+
p.description = "Tiny graphs."
|
11
|
+
p.email = 'boss@topfunky.com'
|
12
|
+
p.summary = "Tiny graphs."
|
13
|
+
p.url = "http://nubyonrails.com/pages/sparklines"
|
14
|
+
p.clean_globs = ['test/output/*']
|
15
|
+
|
16
|
+
# * extra_deps - An array of rubygem dependencies.
|
17
|
+
end
|
data/lib/sparklines.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
|
2
2
|
require 'rubygems'
|
3
3
|
require 'RMagick'
|
4
|
-
require 'mathn'
|
5
4
|
|
6
5
|
=begin rdoc
|
7
6
|
|
@@ -56,6 +55,7 @@ Graph types:
|
|
56
55
|
pie
|
57
56
|
smooth
|
58
57
|
bar
|
58
|
+
whisker
|
59
59
|
|
60
60
|
General Defaults:
|
61
61
|
|
@@ -74,7 +74,7 @@ Licensed under the MIT license.
|
|
74
74
|
=end
|
75
75
|
class Sparklines
|
76
76
|
|
77
|
-
VERSION = '0.4.
|
77
|
+
VERSION = '0.4.1'
|
78
78
|
|
79
79
|
@@label_margin = 5.0
|
80
80
|
@@pointsize = 10.0
|
@@ -109,7 +109,7 @@ class Sparklines
|
|
109
109
|
:label => nil
|
110
110
|
}
|
111
111
|
|
112
|
-
#
|
112
|
+
# HACK for HashWithIndifferentAccess
|
113
113
|
options_sym = Hash.new
|
114
114
|
options.keys.each do |key|
|
115
115
|
options_sym[key.to_sym] = options[key]
|
@@ -119,7 +119,7 @@ class Sparklines
|
|
119
119
|
|
120
120
|
# Call the appropriate method for actual plotting.
|
121
121
|
sparkline = self.new(data, options_sym)
|
122
|
-
if %w(area bar pie smooth discrete).include? options_sym[:type]
|
122
|
+
if %w(area bar pie smooth discrete whisker).include? options_sym[:type]
|
123
123
|
sparkline.send options_sym[:type]
|
124
124
|
else
|
125
125
|
sparkline.plot_error options_sym
|
@@ -133,7 +133,7 @@ class Sparklines
|
|
133
133
|
end
|
134
134
|
end
|
135
135
|
|
136
|
-
end
|
136
|
+
end # class methods
|
137
137
|
|
138
138
|
def initialize(data=[], options={})
|
139
139
|
@data = Array(data)
|
@@ -141,6 +141,7 @@ class Sparklines
|
|
141
141
|
normalize_data
|
142
142
|
end
|
143
143
|
|
144
|
+
##
|
144
145
|
# Creates a continuous area sparkline. Relevant options.
|
145
146
|
#
|
146
147
|
# :step - An integer that determines the distance between each point on the sparkline. Defaults to 2.
|
@@ -164,6 +165,7 @@ class Sparklines
|
|
164
165
|
# :above_color - A string or color code representing the color to draw values above or equal the upper value. Defaults to red.
|
165
166
|
#
|
166
167
|
# :below_color - A string or color code representing the color to draw values below the upper value. Defaults to gray.
|
168
|
+
|
167
169
|
def area
|
168
170
|
|
169
171
|
step = @options[:step].to_i
|
@@ -231,9 +233,9 @@ class Sparklines
|
|
231
233
|
@canvas.to_blob
|
232
234
|
end
|
233
235
|
|
236
|
+
##
|
237
|
+
# A bar graph.
|
234
238
|
|
235
|
-
# Draws a bar graph.
|
236
|
-
#
|
237
239
|
def bar
|
238
240
|
step = @options[:step].to_i
|
239
241
|
height = @options[:height].to_f
|
@@ -260,6 +262,7 @@ class Sparklines
|
|
260
262
|
end
|
261
263
|
|
262
264
|
|
265
|
+
##
|
263
266
|
# Creates a discretized sparkline
|
264
267
|
#
|
265
268
|
# :height - An integer that determines what the height of the sparkline will be. Defaults to 14
|
@@ -269,6 +272,7 @@ class Sparklines
|
|
269
272
|
# :above_color - A string or color code representing the color to draw values above or equal the upper value. Defaults to red.
|
270
273
|
#
|
271
274
|
# :below_color - A string or color code representing the color to draw values below the upper value. Defaults to gray.
|
275
|
+
|
272
276
|
def discrete
|
273
277
|
|
274
278
|
height = @options[:height].to_i
|
@@ -295,6 +299,7 @@ class Sparklines
|
|
295
299
|
end
|
296
300
|
|
297
301
|
|
302
|
+
##
|
298
303
|
# Creates a pie-chart sparkline
|
299
304
|
#
|
300
305
|
# :diameter - An integer that determines what the size of the sparkline will be. Defaults to 20
|
@@ -302,8 +307,8 @@ class Sparklines
|
|
302
307
|
# :share_color - A string or color code representing the color to draw the share of the pie represented by percent. Defaults to red.
|
303
308
|
#
|
304
309
|
# :remain_color - A string or color code representing the color to draw the pie not taken by the share color. Defaults to lightgrey.
|
305
|
-
def pie
|
306
310
|
|
311
|
+
def pie
|
307
312
|
diameter = @options[:diameter].to_i
|
308
313
|
background_color = @options[:background_color]
|
309
314
|
|
@@ -362,6 +367,7 @@ class Sparklines
|
|
362
367
|
end
|
363
368
|
|
364
369
|
|
370
|
+
##
|
365
371
|
# Creates a smooth sparkline.
|
366
372
|
#
|
367
373
|
# :step - An integer that determines the distance between each point on the sparkline. Defaults to 2.
|
@@ -379,6 +385,7 @@ class Sparklines
|
|
379
385
|
# :max_color - A string or color code representing the color that the dot drawn at the largest value will be displayed as. Defaults to green.
|
380
386
|
#
|
381
387
|
# :last_color - A string or color code representing the color that the dot drawn at the last value will be displayed as. Defaults to red.
|
388
|
+
|
382
389
|
def smooth
|
383
390
|
|
384
391
|
step = @options[:step].to_i
|
@@ -416,7 +423,65 @@ class Sparklines
|
|
416
423
|
end
|
417
424
|
|
418
425
|
|
426
|
+
##
|
427
|
+
# Creates a whisker sparkline to track on/off type data. There are five states:
|
428
|
+
# on, off, no value, exceptional on, exceptional off. On values create an up
|
429
|
+
# whisker and off values create a down whisker. Exceptional values may be
|
430
|
+
# colored differently than regular values to indicate, for example, a shut out.
|
431
|
+
# No value produces an empty row to indicate a tie.
|
432
|
+
#
|
433
|
+
# * results - an array of integer values between -2 and 2. -2 is exceptional
|
434
|
+
# down, 1 is regular down, 0 is no value, 1 is up, and 2 is exceptional up.
|
435
|
+
# * options - a hash that takes parameters
|
436
|
+
#
|
437
|
+
# :height - height of the sparkline
|
438
|
+
#
|
439
|
+
# :whisker_color - the color of regular whiskers; defaults to black
|
440
|
+
#
|
441
|
+
# :exception_color - the color of exceptional whiskers; defaults to red
|
442
|
+
|
443
|
+
def whisker
|
444
|
+
|
445
|
+
# step = @options[:step].to_i
|
446
|
+
height = @options[:height].to_i
|
447
|
+
background_color = @options[:background_color]
|
448
|
+
|
449
|
+
create_canvas((@data.size - 1) * 2, height, background_color)
|
450
|
+
|
451
|
+
whisker_color = @options[:whisker_color] || 'black'
|
452
|
+
exception_color = @options[:exception_color] || 'red'
|
453
|
+
|
454
|
+
i = 0
|
455
|
+
@data.each do |r|
|
456
|
+
color = whisker_color
|
457
|
+
|
458
|
+
if ( (r == 2 || r == -2) && exception_color )
|
459
|
+
color = exception_color
|
460
|
+
end
|
461
|
+
|
462
|
+
y_mid_point = (r >= 1) ? (@canvas.rows/2.0 - 1).ceil : (@canvas.rows/2.0).floor
|
463
|
+
|
464
|
+
y_end_point = y_mid_point
|
465
|
+
if ( r > 0)
|
466
|
+
y_end_point = 0
|
467
|
+
end
|
468
|
+
|
469
|
+
if ( r < 0 )
|
470
|
+
y_end_point = @canvas.rows
|
471
|
+
end
|
472
|
+
|
473
|
+
@draw.stroke( color )
|
474
|
+
@draw.line( i, y_mid_point, i, y_end_point )
|
475
|
+
i += 2
|
476
|
+
end
|
477
|
+
|
478
|
+
@draw.draw(@canvas)
|
479
|
+
@canvas.to_blob
|
480
|
+
end
|
481
|
+
|
482
|
+
##
|
419
483
|
# Draw the error Sparkline.
|
484
|
+
|
420
485
|
def plot_error(options={})
|
421
486
|
create_canvas(40, 15, 'white')
|
422
487
|
|
@@ -439,23 +504,27 @@ private
|
|
439
504
|
end
|
440
505
|
end
|
441
506
|
|
442
|
-
|
507
|
+
##
|
508
|
+
# * :arr - an array of points (represented as two element arrays)
|
509
|
+
|
443
510
|
def open_ended_polyline(arr)
|
444
511
|
0.upto(arr.length - 2) { |i|
|
445
512
|
@draw.line(arr[i][0], arr[i][1], arr[i+1][0], arr[i+1][1])
|
446
513
|
}
|
447
514
|
end
|
448
515
|
|
516
|
+
##
|
449
517
|
# Create an image to draw on and a drawable to do the drawing with.
|
450
518
|
#
|
451
|
-
# TODO Refactor into smaller
|
519
|
+
# TODO Refactor into smaller methods
|
520
|
+
|
452
521
|
def create_canvas(w, h, bkg_col)
|
453
522
|
@draw = Magick::Draw.new
|
454
523
|
@draw.pointsize = @@pointsize # TODO Use height
|
455
524
|
@canvas = Magick::Image.new(w , h) { self.background_color = bkg_col }
|
456
|
-
|
525
|
+
|
457
526
|
# Make room for label and last value
|
458
|
-
|
527
|
+
unless @options[:label].nil?
|
459
528
|
@options[:has_last] = true
|
460
529
|
@label_width = calculate_width(@options[:label])
|
461
530
|
@data_last_width = calculate_width(@data.last)
|
@@ -463,19 +532,19 @@ private
|
|
463
532
|
@label_and_data_last_width = @label_width + @data_last_width + @@label_margin * 7.0
|
464
533
|
w += @label_and_data_last_width
|
465
534
|
end
|
466
|
-
|
535
|
+
|
467
536
|
@canvas = Magick::Image.new(w , h) { self.background_color = bkg_col }
|
468
537
|
@canvas.format = "PNG"
|
469
|
-
|
538
|
+
|
470
539
|
# Draw label and last value
|
471
|
-
|
540
|
+
unless @options[:label].nil?
|
472
541
|
if ENV.has_key?('MAGICK_FONT_PATH')
|
473
542
|
vera_font_path = File.expand_path('Vera.ttf', ENV['MAGICK_FONT_PATH'])
|
474
543
|
@font = File.exists?(vera_font_path) ? vera_font_path : nil
|
475
544
|
else
|
476
545
|
@font = nil
|
477
546
|
end
|
478
|
-
|
547
|
+
|
479
548
|
@draw.fill = 'black'
|
480
549
|
@draw.font = @font if @font
|
481
550
|
@draw.gravity = Magick::WestGravity
|
@@ -483,7 +552,7 @@ private
|
|
483
552
|
@label_width, 1.0,
|
484
553
|
w - @label_and_data_last_width + @@label_margin, h - calculate_caps_height/2.0,
|
485
554
|
@options[:label])
|
486
|
-
|
555
|
+
|
487
556
|
@draw.fill = 'red'
|
488
557
|
@draw.annotate( @canvas,
|
489
558
|
@data_last_width, 1.0,
|
@@ -491,9 +560,11 @@ private
|
|
491
560
|
@data.last.to_s)
|
492
561
|
end
|
493
562
|
end
|
494
|
-
|
563
|
+
|
564
|
+
##
|
495
565
|
# Utility to draw a coloured box
|
496
566
|
# Centred on pt, offset off in each direction, fill color is col
|
567
|
+
|
497
568
|
def drawbox(pt, offset, color)
|
498
569
|
@draw.stroke 'transparent'
|
499
570
|
@draw.fill(color)
|
@@ -508,5 +579,4 @@ private
|
|
508
579
|
@draw.get_type_metrics(@canvas, 'X').height
|
509
580
|
end
|
510
581
|
|
511
|
-
|
512
582
|
end
|
@@ -21,10 +21,29 @@ class SparklinesTest < Test::Unit::TestCase
|
|
21
21
|
|
22
22
|
def test_each_graph_with_label
|
23
23
|
%w{pie area discrete smooth bar}.each do |type|
|
24
|
-
quick_graph("labeled_#{type}", :type => type, :label => '
|
24
|
+
quick_graph("labeled_#{type}", :type => type, :label => 'Glucose')
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
|
+
def test_whisker_random
|
29
|
+
# Need data ranging from -2 to +2
|
30
|
+
@data = (1..40).map { |i| rand(3) * (rand(2) == 1 ? -1 : 1) }
|
31
|
+
quick_graph("whisker", :type => 'whisker')
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_whisker_non_exceptional
|
35
|
+
@data = [1,1,1,1,1,1,1,1,1,1,1,1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1]
|
36
|
+
quick_graph("whisker_non_exceptional", :type => 'whisker')
|
37
|
+
end
|
38
|
+
|
39
|
+
##
|
40
|
+
# Send random values in the range (-9..9)
|
41
|
+
|
42
|
+
def test_whisker_junk
|
43
|
+
@data = (1..40).map { |i| rand(10) * (rand(2) == 1 ? -1 : 1) }
|
44
|
+
quick_graph("whisker_junk", :type => 'whisker')
|
45
|
+
end
|
46
|
+
|
28
47
|
def test_pie
|
29
48
|
# Test extremes which previously did not work right
|
30
49
|
[0, 1, 45, 95, 99, 100].each do |value|
|
metadata
CHANGED
@@ -1,18 +1,19 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.
|
2
|
+
rubygems_version: 0.9.0
|
3
3
|
specification_version: 1
|
4
4
|
name: sparklines
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.4.
|
7
|
-
date: 2006-
|
8
|
-
summary: Tiny graphs
|
6
|
+
version: 0.4.1
|
7
|
+
date: 2006-10-20 00:00:00 -07:00
|
8
|
+
summary: Tiny graphs.
|
9
9
|
require_paths:
|
10
10
|
- lib
|
11
|
+
- test
|
11
12
|
email: boss@topfunky.com
|
12
|
-
homepage: http://
|
13
|
+
homepage: http://nubyonrails.com/pages/sparklines
|
13
14
|
rubyforge_project: sparklines
|
14
|
-
description:
|
15
|
-
autorequire:
|
15
|
+
description: Tiny graphs.
|
16
|
+
autorequire:
|
16
17
|
default_executable:
|
17
18
|
bindir: bin
|
18
19
|
has_rdoc: true
|
@@ -25,18 +26,19 @@ required_ruby_version: !ruby/object:Gem::Version::Requirement
|
|
25
26
|
platform: ruby
|
26
27
|
signing_key:
|
27
28
|
cert_chain:
|
29
|
+
post_install_message:
|
28
30
|
authors:
|
29
31
|
- Geoffrey Grosenbach
|
30
32
|
files:
|
31
|
-
-
|
33
|
+
- Rakefile
|
34
|
+
- Manifest.txt
|
32
35
|
- README
|
33
36
|
- CHANGELOG
|
34
|
-
- MIT-LICENSE
|
35
37
|
- lib/sparklines.rb
|
36
|
-
- test/
|
38
|
+
- test/test_all.rb
|
37
39
|
- test/output
|
38
|
-
test_files:
|
39
|
-
|
40
|
+
test_files:
|
41
|
+
- test/test_all.rb
|
40
42
|
rdoc_options: []
|
41
43
|
|
42
44
|
extra_rdoc_files: []
|
@@ -45,7 +47,15 @@ executables: []
|
|
45
47
|
|
46
48
|
extensions: []
|
47
49
|
|
48
|
-
requirements:
|
49
|
-
- none
|
50
|
-
dependencies: []
|
50
|
+
requirements: []
|
51
51
|
|
52
|
+
dependencies:
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: hoe
|
55
|
+
version_requirement:
|
56
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: 1.1.1
|
61
|
+
version:
|
data/MIT-LICENSE
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
Copyright (c) 2005 Geoffrey Grosenbach boss@topfunky.com
|
2
|
-
|
3
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
-
a copy of this software and associated documentation files (the
|
5
|
-
"Software"), to deal in the Software without restriction, including
|
6
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
-
permit persons to whom the Software is furnished to do so, subject to
|
9
|
-
the following conditions:
|
10
|
-
|
11
|
-
The above copyright notice and this permission notice shall be
|
12
|
-
included in all copies or substantial portions of the Software.
|
13
|
-
|
14
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
-
|
data/rakefile
DELETED
@@ -1,213 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'rake'
|
3
|
-
require 'rake/testtask'
|
4
|
-
require 'rake/rdoctask'
|
5
|
-
require 'rake/packagetask'
|
6
|
-
require 'rake/gempackagetask'
|
7
|
-
require 'rake/contrib/rubyforgepublisher'
|
8
|
-
|
9
|
-
$:.unshift(File.dirname(__FILE__) + "/lib")
|
10
|
-
require 'sparklines'
|
11
|
-
|
12
|
-
PKG_NAME = 'sparklines'
|
13
|
-
PKG_VERSION = Sparklines::VERSION
|
14
|
-
PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
|
15
|
-
|
16
|
-
RELEASE_NAME = "REL #{PKG_VERSION}"
|
17
|
-
|
18
|
-
RUBY_FORGE_PROJECT = "sparklines"
|
19
|
-
RUBY_FORGE_USER = "topfunky"
|
20
|
-
|
21
|
-
desc "Default Task"
|
22
|
-
task :default => [ :clean, :test ]
|
23
|
-
|
24
|
-
desc "Clean images generated by tests"
|
25
|
-
task :clean do
|
26
|
-
rm FileList['test/output/*.png']
|
27
|
-
rm_rf "pkg"
|
28
|
-
end
|
29
|
-
|
30
|
-
# Build a graphic file by running a single test.
|
31
|
-
#
|
32
|
-
# rake bar_extreme_values.png
|
33
|
-
# => Runs test_extreme_values
|
34
|
-
|
35
|
-
rule ".png" do |t|
|
36
|
-
test_name = t.name.gsub(/\.png/, '')
|
37
|
-
Rake::Task[:clean].invoke
|
38
|
-
sh "ruby -Ilib:test test/all_test.rb -n /^test_#{test_name}/"
|
39
|
-
end
|
40
|
-
|
41
|
-
# Run the unit tests
|
42
|
-
Rake::TestTask.new { |t|
|
43
|
-
t.libs << "test"
|
44
|
-
t.pattern = 'test/*_test.rb'
|
45
|
-
t.verbose = true
|
46
|
-
}
|
47
|
-
|
48
|
-
|
49
|
-
# Genereate the RDoc documentation
|
50
|
-
Rake::RDocTask.new { |rdoc|
|
51
|
-
rdoc.rdoc_dir = 'doc'
|
52
|
-
rdoc.title = "Sparklines -- Tiny graphs"
|
53
|
-
rdoc.options << '--line-numbers --inline-source --main README --accessor adv_attr_accessor=M'
|
54
|
-
rdoc.template = "#{ENV['template']}.rb" if ENV['template']
|
55
|
-
rdoc.rdoc_files.include('README', 'CHANGELOG')
|
56
|
-
rdoc.rdoc_files.include('lib/sparklines.rb')
|
57
|
-
rdoc.rdoc_files.include('lib/sparklines/*.rb')
|
58
|
-
}
|
59
|
-
|
60
|
-
|
61
|
-
# Create compressed packages
|
62
|
-
spec = Gem::Specification.new do |s|
|
63
|
-
s.platform = Gem::Platform::RUBY
|
64
|
-
s.name = PKG_NAME
|
65
|
-
s.summary = "Tiny graphs for concise data."
|
66
|
-
s.description = %q{Make tiny graphs for use on websites or documents.}
|
67
|
-
s.version = PKG_VERSION
|
68
|
-
|
69
|
-
s.author = "Geoffrey Grosenbach"
|
70
|
-
s.email = "boss@topfunky.com"
|
71
|
-
s.rubyforge_project = RUBY_FORGE_PROJECT
|
72
|
-
s.homepage = "http://www.topfunky.com"
|
73
|
-
|
74
|
-
s.has_rdoc = true
|
75
|
-
s.requirements << 'none'
|
76
|
-
s.require_path = 'lib'
|
77
|
-
s.autorequire = 'gruff'
|
78
|
-
|
79
|
-
s.files = [ "rakefile", "README", "CHANGELOG", "MIT-LICENSE" ]
|
80
|
-
s.files = s.files + Dir.glob( "lib/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
|
81
|
-
s.files = s.files + Dir.glob( "test/**/*" ).delete_if { |item| item.include?( "\.svn" ) || item.include?("\.png") }
|
82
|
-
end
|
83
|
-
|
84
|
-
Rake::GemPackageTask.new(spec) do |p|
|
85
|
-
p.gem_spec = spec
|
86
|
-
p.need_tar = true
|
87
|
-
p.need_zip = true
|
88
|
-
end
|
89
|
-
|
90
|
-
desc "Hackish copy to sparklines plugin for Rails"
|
91
|
-
task :update_plugin do
|
92
|
-
cp "lib/sparklines.rb", "../plugins/sparklines/lib/sparklines.rb"
|
93
|
-
end
|
94
|
-
|
95
|
-
desc "Publish the API documentation"
|
96
|
-
task :pgem => [:package] do
|
97
|
-
Rake::SshFilePublisher.new("boss@topfunky.com", "public_html/gems/gems", "pkg", "#{PKG_FILE_NAME}.gem").upload
|
98
|
-
end
|
99
|
-
|
100
|
-
desc "Publish the release files to RubyForge."
|
101
|
-
task :release => [:package] do
|
102
|
-
files = ["gem", "tgz", "zip"].map { |ext| "pkg/#{PKG_FILE_NAME}.#{ext}" }
|
103
|
-
|
104
|
-
if RUBY_FORGE_PROJECT then
|
105
|
-
require 'net/http'
|
106
|
-
require 'open-uri'
|
107
|
-
|
108
|
-
project_uri = "http://rubyforge.org/projects/#{RUBY_FORGE_PROJECT}/"
|
109
|
-
project_data = open(project_uri) { |data| data.read }
|
110
|
-
group_id = project_data[/[?&]group_id=(\d+)/, 1]
|
111
|
-
raise "Couldn't get group id" unless group_id
|
112
|
-
|
113
|
-
# This echos password to shell which is a bit sucky
|
114
|
-
if ENV["RUBY_FORGE_PASSWORD"]
|
115
|
-
password = ENV["RUBY_FORGE_PASSWORD"]
|
116
|
-
else
|
117
|
-
print "#{RUBY_FORGE_USER}@rubyforge.org's password: "
|
118
|
-
password = STDIN.gets.chomp
|
119
|
-
end
|
120
|
-
|
121
|
-
login_response = Net::HTTP.start("rubyforge.org", 80) do |http|
|
122
|
-
data = [
|
123
|
-
"login=1",
|
124
|
-
"form_loginname=#{RUBY_FORGE_USER}",
|
125
|
-
"form_pw=#{password}"
|
126
|
-
].join("&")
|
127
|
-
http.post("/account/login.php", data)
|
128
|
-
end
|
129
|
-
|
130
|
-
cookie = login_response["set-cookie"]
|
131
|
-
raise "Login failed" unless cookie
|
132
|
-
headers = { "Cookie" => cookie }
|
133
|
-
|
134
|
-
release_uri = "http://rubyforge.org/frs/admin/?group_id=#{group_id}"
|
135
|
-
release_data = open(release_uri, headers) { |data| data.read }
|
136
|
-
package_id = release_data[/[?&]package_id=(\d+)/, 1]
|
137
|
-
raise "Couldn't get package id" unless package_id
|
138
|
-
|
139
|
-
first_file = true
|
140
|
-
release_id = ""
|
141
|
-
|
142
|
-
files.each do |filename|
|
143
|
-
basename = File.basename(filename)
|
144
|
-
file_ext = File.extname(filename)
|
145
|
-
file_data = File.open(filename, "rb") { |file| file.read }
|
146
|
-
|
147
|
-
puts "Releasing #{basename}..."
|
148
|
-
|
149
|
-
release_response = Net::HTTP.start("rubyforge.org", 80) do |http|
|
150
|
-
release_date = Time.now.strftime("%Y-%m-%d %H:%M")
|
151
|
-
type_map = {
|
152
|
-
".zip" => "3000",
|
153
|
-
".tgz" => "3110",
|
154
|
-
".gz" => "3110",
|
155
|
-
".gem" => "1400"
|
156
|
-
}; type_map.default = "9999"
|
157
|
-
type = type_map[file_ext]
|
158
|
-
boundary = "rubyqMY6QN9bp6e4kS21H4y0zxcvoor"
|
159
|
-
|
160
|
-
query_hash = if first_file then
|
161
|
-
{
|
162
|
-
"group_id" => group_id,
|
163
|
-
"package_id" => package_id,
|
164
|
-
"release_name" => RELEASE_NAME,
|
165
|
-
"release_date" => release_date,
|
166
|
-
"type_id" => type,
|
167
|
-
"processor_id" => "8000", # Any
|
168
|
-
"release_notes" => "",
|
169
|
-
"release_changes" => "",
|
170
|
-
"preformatted" => "1",
|
171
|
-
"submit" => "1"
|
172
|
-
}
|
173
|
-
else
|
174
|
-
{
|
175
|
-
"group_id" => group_id,
|
176
|
-
"release_id" => release_id,
|
177
|
-
"package_id" => package_id,
|
178
|
-
"step2" => "1",
|
179
|
-
"type_id" => type,
|
180
|
-
"processor_id" => "8000", # Any
|
181
|
-
"submit" => "Add This File"
|
182
|
-
}
|
183
|
-
end
|
184
|
-
|
185
|
-
query = "?" + query_hash.map do |(name, value)|
|
186
|
-
[name, URI.encode(value)].join("=")
|
187
|
-
end.join("&")
|
188
|
-
|
189
|
-
data = [
|
190
|
-
"--" + boundary,
|
191
|
-
"Content-Disposition: form-data; name=\"userfile\"; filename=\"#{basename}\"",
|
192
|
-
"Content-Type: application/octet-stream",
|
193
|
-
"Content-Transfer-Encoding: binary",
|
194
|
-
"", file_data, ""
|
195
|
-
].join("\x0D\x0A")
|
196
|
-
|
197
|
-
release_headers = headers.merge(
|
198
|
-
"Content-Type" => "multipart/form-data; boundary=#{boundary}"
|
199
|
-
)
|
200
|
-
|
201
|
-
target = first_file ? "/frs/admin/qrs.php" : "/frs/admin/editrelease.php"
|
202
|
-
http.post(target + query, data, release_headers)
|
203
|
-
end
|
204
|
-
|
205
|
-
if first_file then
|
206
|
-
release_id = release_response.body[/release_id=(\d+)/, 1]
|
207
|
-
raise("Couldn't get release id") unless release_id
|
208
|
-
end
|
209
|
-
|
210
|
-
first_file = false
|
211
|
-
end
|
212
|
-
end
|
213
|
-
end
|