dates2svg 0.0.1.beta1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +26 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/dates2svg.gemspec +24 -0
- data/lib/dates2svg/version.rb +3 -0
- data/lib/dates2svg.rb +194 -0
- data/spec/lib/dates2svg_spec.rb +130 -0
- data/spec/spec_helper.rb +17 -0
- metadata +109 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
Copyright (c) 2012-2013. The Board of Trustees of the Leland Stanford Junior University. All rights reserved.
|
2
|
+
|
3
|
+
Redistribution and use of this distribution in source and binary forms, with or without modification, are permitted provided that: The above copyright notice and this permission notice appear in all copies and supporting documentation; The name, identifiers, and trademarks of The Board of Trustees of the Leland Stanford Junior University are not used in advertising or publicity without the express prior written permission of The Board of Trustees of the Leland Stanford Junior University; Recipients acknowledge that this distribution is made available as a research courtesy, "as is", potentially with defects, without any obligation on the part of The Board of Trustees of the Leland Stanford Junior University to provide support, services, or repair;
|
4
|
+
|
5
|
+
THE BOARD OF TRUSTEES OF THE LELAND STANFORD JUNIOR UNIVERSITY DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN NO EVENT SHALL THE BOARD OF TRUSTEES OF THE LELAND STANFORD JUNIOR UNIVERSITY BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
6
|
+
|
7
|
+
MIT License
|
8
|
+
|
9
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
10
|
+
a copy of this software and associated documentation files (the
|
11
|
+
"Software"), to deal in the Software without restriction, including
|
12
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
13
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
14
|
+
permit persons to whom the Software is furnished to do so, subject to
|
15
|
+
the following conditions:
|
16
|
+
|
17
|
+
The above copyright notice and this permission notice shall be
|
18
|
+
included in all copies or substantial portions of the Software.
|
19
|
+
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
21
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
22
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
23
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
24
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
25
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
26
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Dates2svg
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'dates2svg'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install dates2svg
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/dates2svg.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'dates2svg/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "dates2svg"
|
8
|
+
spec.version = Dates2SVG::VERSION
|
9
|
+
spec.authors = ["Jessie Keck"]
|
10
|
+
spec.email = ["jessie.keck@gmail.com"]
|
11
|
+
spec.description = %q{Generate a SVG month grid w/ heatmap based on array of dates.}
|
12
|
+
spec.summary = %q{Turn an array of objects that have a #value method w/ YYYY-MM-DD Date and a #hits method w/ the number of items in that month into an SVG month grid with heatmap.}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec"
|
24
|
+
end
|
data/lib/dates2svg.rb
ADDED
@@ -0,0 +1,194 @@
|
|
1
|
+
require "dates2svg/version"
|
2
|
+
|
3
|
+
class Dates2SVG
|
4
|
+
BOX_SIZE = 15
|
5
|
+
BORDER = 1
|
6
|
+
BOX_WITH_BORDER = (BOX_SIZE + BORDER)
|
7
|
+
def initialize(dates, options={})
|
8
|
+
@dates = dates
|
9
|
+
@options = options
|
10
|
+
parse_dates
|
11
|
+
end
|
12
|
+
|
13
|
+
def parse_dates
|
14
|
+
@dates.map do |date|
|
15
|
+
date_from_facet_value(date)
|
16
|
+
end.sort do |a, b|
|
17
|
+
a.year.to_i <=> b.year.to_i
|
18
|
+
end.group_by(&:year).each do |year, dates|
|
19
|
+
years << Dates2SVG::Year.new(year, dates)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def date_from_facet_value(facet)
|
24
|
+
facet.value[/^(\d{4})-(\d{2})-(\d{2})/]
|
25
|
+
Dates2SVG::DateWithValue.new(:year => $1, :month => $2, :day => $3, :hits => facet.hits)
|
26
|
+
end
|
27
|
+
|
28
|
+
def years
|
29
|
+
@years ||= []
|
30
|
+
end
|
31
|
+
|
32
|
+
def max
|
33
|
+
@max ||= years.map{|year| year.months.map{|month| month.hits} }.flatten.max
|
34
|
+
end
|
35
|
+
|
36
|
+
def color_range
|
37
|
+
self.class.color_range(@options.merge(:max => @max))
|
38
|
+
end
|
39
|
+
|
40
|
+
def color_options
|
41
|
+
@options[:color_options] || self.class.color_options
|
42
|
+
end
|
43
|
+
|
44
|
+
def to_svg
|
45
|
+
svg = ""
|
46
|
+
# + 35 and +50 gives us the space for the year month text
|
47
|
+
svg << "<svg height='#{(12 * BOX_WITH_BORDER) + 35}' width='#{(all_years.to_a.length * BOX_WITH_BORDER) + 50}'>"
|
48
|
+
svg << "<g transform='translate(20,35)'>"
|
49
|
+
all_years.each_with_index do |year, index|
|
50
|
+
selected_years = years.select{|y| y.year.to_i == year.to_i }
|
51
|
+
unless selected_years.length == 0
|
52
|
+
svg << selected_years.first.to_svg(@options.merge(:index => index, :max => max))
|
53
|
+
else
|
54
|
+
svg << Dates2SVG::Year.new(year, []).to_svg(@options.merge(:index => index, :max => max))
|
55
|
+
end
|
56
|
+
end
|
57
|
+
svg << calendar_year_listing
|
58
|
+
svg << calendar_month_listing
|
59
|
+
svg << "</g>"
|
60
|
+
svg << "</svg>"
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.color_range(options={})
|
64
|
+
max_hits = options[:max] || 3000
|
65
|
+
section = (max_hits) / 5
|
66
|
+
colors = {}
|
67
|
+
color_options = options[:color_options] || self.color_options
|
68
|
+
ranges = [[0], (1..(section * 1)),
|
69
|
+
(((section * 1) + 1)..(section * 2)),
|
70
|
+
(((section * 2) + 1)..(section * 3)),
|
71
|
+
(((section * 3) + 1)..(section * 4)),
|
72
|
+
(((section * 4) + 1)..max_hits)]
|
73
|
+
color_options.each_with_index do |color, index|
|
74
|
+
unless ranges[index].is_a?(Range) and [ranges[index].first, ranges[index].last].include?(0)
|
75
|
+
colors[ranges[index]] = color
|
76
|
+
end
|
77
|
+
end
|
78
|
+
colors
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.color_options(options={})
|
82
|
+
options[:color_options] || ["#EEEEEE", "#330000", "#660000", "#990000", "#CC0000", "#FF0000"]
|
83
|
+
end
|
84
|
+
|
85
|
+
private
|
86
|
+
|
87
|
+
def all_years
|
88
|
+
@options[:year_range] || years.map{|y| y.year }
|
89
|
+
end
|
90
|
+
|
91
|
+
def calendar_year_listing
|
92
|
+
svg = ""
|
93
|
+
all_years.each_with_index do |year, index|
|
94
|
+
svg << "<text x='3' y='#{(BOX_WITH_BORDER * index) + 20}' transform='rotate(-90)' class='year'>#{year}</text>"
|
95
|
+
end
|
96
|
+
svg
|
97
|
+
end
|
98
|
+
|
99
|
+
def calendar_month_listing
|
100
|
+
svg = ""
|
101
|
+
["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", " Oct", "Nov", "Dec"].each_with_index do |month, index|
|
102
|
+
svg << "<text text-anchor='middle' class='cmonth' dx='0' dy='#{(BOX_WITH_BORDER * index) + 10}'>#{month}</text>"
|
103
|
+
end
|
104
|
+
svg
|
105
|
+
end
|
106
|
+
|
107
|
+
class DateWithValue
|
108
|
+
attr_reader :year, :month, :day, :hits
|
109
|
+
def initialize(ops={})
|
110
|
+
@year = ops[:year]
|
111
|
+
@month = ops[:month]
|
112
|
+
@day = ops[:day]
|
113
|
+
@hits = ops[:hits]
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
class Year
|
118
|
+
attr_reader :year
|
119
|
+
def initialize(year, dates)
|
120
|
+
@year = year
|
121
|
+
@dates = dates
|
122
|
+
parse_dates
|
123
|
+
end
|
124
|
+
|
125
|
+
def parse_dates
|
126
|
+
@dates.sort do |a, b|
|
127
|
+
a.month.to_i <=> b.month.to_i
|
128
|
+
end.group_by(&:month).map do |month, dates|
|
129
|
+
months << Dates2SVG::Month.new(@year, month, dates)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def months
|
134
|
+
@months ||= []
|
135
|
+
end
|
136
|
+
|
137
|
+
def to_svg(options={})
|
138
|
+
svg = ""
|
139
|
+
svg << "<g transform='translate(#{(BOX_WITH_BORDER * options[:index]) + 12},0)'>"
|
140
|
+
all_months.each_with_index do |month, index|
|
141
|
+
unless months.select{|m| m.month == month}.length == 0
|
142
|
+
svg << months.select{|m| m.month == month}.first.to_svg(options.merge(:index => index))
|
143
|
+
else
|
144
|
+
svg << Dates2SVG::Month.new(@year, month, []).to_svg(options.merge(:index => index))
|
145
|
+
end
|
146
|
+
end
|
147
|
+
svg << "</g>"
|
148
|
+
end
|
149
|
+
|
150
|
+
private
|
151
|
+
|
152
|
+
def all_months
|
153
|
+
["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"]
|
154
|
+
end
|
155
|
+
|
156
|
+
end
|
157
|
+
|
158
|
+
class Month
|
159
|
+
attr_reader :year, :month
|
160
|
+
def initialize(year, month, dates)
|
161
|
+
@year = year
|
162
|
+
@month = month
|
163
|
+
@dates = dates
|
164
|
+
end
|
165
|
+
def hits
|
166
|
+
@hits ||= (@dates.map{|d| d.hits.to_i }.inject(:+) || 0)
|
167
|
+
end
|
168
|
+
|
169
|
+
def to_svg(options={})
|
170
|
+
svg = ""
|
171
|
+
svg << "<rect data-hits='#{hits}' data-year='#{@year}' data-month='#{@month}' class='month' width='#{BOX_SIZE}' height='#{BOX_SIZE}' y='#{BOX_WITH_BORDER * options[:index]}' style='fill: #{color(options)};'>"
|
172
|
+
svg << "<title>#{hits} hits on #{@year}-#{@month}</title>"
|
173
|
+
svg << "</rect>"
|
174
|
+
end
|
175
|
+
|
176
|
+
private
|
177
|
+
|
178
|
+
def color(options={})
|
179
|
+
max_hits = options[:max] || 3000
|
180
|
+
section = (max_hits / 5)
|
181
|
+
max = section * 5
|
182
|
+
|
183
|
+
return Dates2SVG.color_options(options).last if hits > max
|
184
|
+
colors = Dates2SVG.color_range(options)
|
185
|
+
begin
|
186
|
+
# .first turns the hash into an array and .last gets the value
|
187
|
+
colors.select{|k,v| k.include?(hits) }.first.last
|
188
|
+
rescue
|
189
|
+
Dates2SVG.color_options(options).first
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "dates2svg"
|
3
|
+
|
4
|
+
class DateValue
|
5
|
+
attr_reader :value, :hits
|
6
|
+
def initialize(ops={})
|
7
|
+
@value = ops[:value]
|
8
|
+
@hits = ops[:hits]
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe Dates2SVG do
|
13
|
+
before(:all) do
|
14
|
+
@hits_values = [98, 401, 500, 400, 100]
|
15
|
+
@dates = [
|
16
|
+
DateValue.new(:value=>"1779-05-02", :hits =>6),
|
17
|
+
|
18
|
+
DateValue.new(:value=>"1789-01-05", :hits =>8),
|
19
|
+
DateValue.new(:value=>"1789-01-11", :hits =>20),
|
20
|
+
DateValue.new(:value=>"1789-01-12", :hits =>10),
|
21
|
+
|
22
|
+
DateValue.new(:value=>"1789-03-10", :hits =>50),
|
23
|
+
DateValue.new(:value=>"1789-03-15", :hits =>100),
|
24
|
+
DateValue.new(:value=>"1789-03-20", :hits =>400),
|
25
|
+
DateValue.new(:value=>"1789-03-20", :hits =>323),
|
26
|
+
DateValue.new(:value=>"1789-03-14", :hits =>122),
|
27
|
+
DateValue.new(:value=>"1789-03-29", :hits =>426),
|
28
|
+
|
29
|
+
DateValue.new(:value=>"1789-01-12", :hits =>10),
|
30
|
+
|
31
|
+
DateValue.new(:value=>"1789-06-30", :hits =>5),
|
32
|
+
|
33
|
+
DateValue.new(:value=>"1789-07-01", :hits =>7),
|
34
|
+
DateValue.new(:value=>"1789-07-02", :hits =>4),
|
35
|
+
DateValue.new(:value=>"1789-07-03", :hits =>5),
|
36
|
+
DateValue.new(:value=>"1789-07-04", :hits =>7),
|
37
|
+
DateValue.new(:value=>"1789-07-06", :hits =>6),
|
38
|
+
|
39
|
+
DateValue.new(:value=>"1790-06-30", :hits =>40),
|
40
|
+
|
41
|
+
DateValue.new(:value=>"1790-07-01", :hits =>@hits_values[0]),
|
42
|
+
DateValue.new(:value=>"1790-07-02", :hits =>@hits_values[1]),
|
43
|
+
DateValue.new(:value=>"1790-07-03", :hits =>@hits_values[2]),
|
44
|
+
DateValue.new(:value=>"1790-07-04", :hits =>@hits_values[3]),
|
45
|
+
DateValue.new(:value=>"1790-07-06", :hits =>@hits_values[4])]
|
46
|
+
@ranges = Dates2SVG.new(@dates)
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "date parsing" do
|
50
|
+
describe "years" do
|
51
|
+
it "should group the years properly" do
|
52
|
+
@ranges.years.length.should_not be 0
|
53
|
+
@ranges.years.length.should == 3
|
54
|
+
@ranges.years.map{|r| r.year }.should == ["1779", "1789", "1790"]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
describe "months" do
|
58
|
+
it "should groups the months properly" do
|
59
|
+
year_1789 = @ranges.years.select{|y| y.year == "1789" }.first
|
60
|
+
year_1789.months.length.should == 4
|
61
|
+
year_1789.months.map{|m| m.month }.should == ["01", "03", "06", "07"]
|
62
|
+
end
|
63
|
+
it "should sum all the hits in the month" do
|
64
|
+
year_1790 = @ranges.years.select{|y| y.year == "1790" }.first
|
65
|
+
year_1790.months.length.should > 1
|
66
|
+
year_1790.months.select{|m| m.month == "07" }.first.hits.should == @hits_values.inject(:+)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe "max hits" do
|
72
|
+
it "should get the maximum number of hits in all months" do
|
73
|
+
@ranges.max.should == @hits_values.inject(:+)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "colors" do
|
78
|
+
describe "color_range" do
|
79
|
+
it "should get the default max_hits when one is not provided" do
|
80
|
+
range = Dates2SVG.color_range
|
81
|
+
range.keys.first.should == [0]
|
82
|
+
range[[0]].should == "#EEEEEE"
|
83
|
+
range.keys.last.should == (2401..3000)
|
84
|
+
range[(2401..3000)].should == "#FF0000"
|
85
|
+
end
|
86
|
+
it "should use the max option passed to provide a differnt color range" do
|
87
|
+
range = Dates2SVG.color_range(:max => 6000)
|
88
|
+
range.keys.first.should == [0]
|
89
|
+
range[[0]].should == "#EEEEEE"
|
90
|
+
range.keys.last.should == (4801..6000)
|
91
|
+
range[(4801..6000)].should == "#FF0000"
|
92
|
+
end
|
93
|
+
it "should use an updated color range if one is provided" do
|
94
|
+
colors = ["black", "purple", "blue", "green", "yellow", "red"]
|
95
|
+
range = Dates2SVG.color_range(:max => 6000, :color_options => colors)
|
96
|
+
range.keys.first.should == [0]
|
97
|
+
range[[0]].should == colors.first
|
98
|
+
range.keys.last.should == (4801..6000)
|
99
|
+
range[(4801..6000)].should == colors.last
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe "svg export" do
|
105
|
+
describe "options" do
|
106
|
+
describe "year_range" do
|
107
|
+
it "should return only the requested years" do
|
108
|
+
@ranges.to_svg.should match(/data-year='1779'/)
|
109
|
+
new_range = Dates2SVG.new(@dates, :year_range => (1785..1790))
|
110
|
+
new_range.to_svg.should_not match(/data-year='1779'/)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
describe "color_options" do
|
114
|
+
it "use the range of color provided" do
|
115
|
+
[Dates2SVG.color_options.first, Dates2SVG.color_options.last].each do |color|
|
116
|
+
@ranges.to_svg.should match(/fill: #{color};/)
|
117
|
+
end
|
118
|
+
new_options = ["black", "purple", "blue", "green", "yellow", "red"]
|
119
|
+
new_range = Dates2SVG.new(@dates, :color_options => new_options).to_svg
|
120
|
+
Dates2SVG.color_options.each do |color|
|
121
|
+
new_range.should_not match(/fill: #{color};/)
|
122
|
+
end
|
123
|
+
[new_options.first, new_options.last].each do |color|
|
124
|
+
new_range.should match(/fill: #{color}/)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
2
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
4
|
+
# loaded once.
|
5
|
+
#
|
6
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
7
|
+
RSpec.configure do |config|
|
8
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
9
|
+
config.run_all_when_everything_filtered = true
|
10
|
+
config.filter_run :focus
|
11
|
+
|
12
|
+
# Run specs in random order to surface order dependencies. If you find an
|
13
|
+
# order dependency and want to debug it, you can fix the order by providing
|
14
|
+
# the seed, which is printed after each run.
|
15
|
+
# --seed 1234
|
16
|
+
config.order = 'random'
|
17
|
+
end
|
metadata
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dates2svg
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1.beta1
|
5
|
+
prerelease: 6
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Jessie Keck
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-04-10 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bundler
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '1.3'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '1.3'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rake
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rspec
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
description: Generate a SVG month grid w/ heatmap based on array of dates.
|
63
|
+
email:
|
64
|
+
- jessie.keck@gmail.com
|
65
|
+
executables: []
|
66
|
+
extensions: []
|
67
|
+
extra_rdoc_files: []
|
68
|
+
files:
|
69
|
+
- .gitignore
|
70
|
+
- .rspec
|
71
|
+
- Gemfile
|
72
|
+
- LICENSE.txt
|
73
|
+
- README.md
|
74
|
+
- Rakefile
|
75
|
+
- dates2svg.gemspec
|
76
|
+
- lib/dates2svg.rb
|
77
|
+
- lib/dates2svg/version.rb
|
78
|
+
- spec/lib/dates2svg_spec.rb
|
79
|
+
- spec/spec_helper.rb
|
80
|
+
homepage: ''
|
81
|
+
licenses:
|
82
|
+
- MIT
|
83
|
+
post_install_message:
|
84
|
+
rdoc_options: []
|
85
|
+
require_paths:
|
86
|
+
- lib
|
87
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
88
|
+
none: false
|
89
|
+
requirements:
|
90
|
+
- - ! '>='
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ! '>'
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: 1.3.1
|
99
|
+
requirements: []
|
100
|
+
rubyforge_project:
|
101
|
+
rubygems_version: 1.8.24
|
102
|
+
signing_key:
|
103
|
+
specification_version: 3
|
104
|
+
summary: ! 'Turn an array of objects that have a #value method w/ YYYY-MM-DD Date
|
105
|
+
and a #hits method w/ the number of items in that month into an SVG month grid with
|
106
|
+
heatmap.'
|
107
|
+
test_files:
|
108
|
+
- spec/lib/dates2svg_spec.rb
|
109
|
+
- spec/spec_helper.rb
|