jekyll-recker 1.16.0 → 2.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5134c19a248e628a2709daf01227163084bfb2dfd81e8d7c828324dddbd13e2d
4
- data.tar.gz: 9710e3c11ea62dda0707dedd0c9771fd8f802682f36140ef4e59af07a6f7aaa9
3
+ metadata.gz: 7f3c029100fd9fc95b7f7b065e17bbb5cd2baf321fd0b3f93aeac96505e816d6
4
+ data.tar.gz: f66cd31401dd09fd965f34372c117dd26ab582cb8d761d5a00fa1a41352c3e31
5
5
  SHA512:
6
- metadata.gz: 7767ff61b4b0ec54f646b207b4742f7f5b1a94d684d78bfa4f9a00ff0920f097c3e3a28106b847bddcebc0105eb9b65794c0adb9cc8e15f3235bac769454d7c7
7
- data.tar.gz: f45942a90efd38657dc4b8fe81073c20b19a6ed2c22eb6e4b46e48c00807f458b429dd28e45a888f4836f728ad8e56251cc56f45c5a2108496e135275a75088e
6
+ metadata.gz: 2171c0a55cb2e419ae0c120880fef8e11fd4d01b554327f2adca939f8a92c5c0e0b37934acf58d64bbf276688cc7785aa4c06b46db5a224be721b71a0a3d4805
7
+ data.tar.gz: f07aadca9f824b3c22bcbca26c208fe29e1ffa6fee993984263456f951d861d58ec2697aed963a9bbd7924c3d8b6282ef2f6857f335ab8a343b3486fef039e88
@@ -6,8 +6,13 @@ require 'jekyll'
6
6
  #
7
7
  # The greatest jekyll plugin in the world
8
8
  module JekyllRecker
9
- autoload :Mixins, 'jekyll_recker/mixins.rb'
9
+ autoload :Date, 'jekyll_recker/date.rb'
10
+ autoload :Entry, 'jekyll_recker/entry.rb'
11
+ autoload :Graphs, 'jekyll_recker/graphs.rb'
12
+ autoload :Logging, 'jekyll_recker/logging.rb'
13
+ autoload :Math, 'jekyll_recker/math.rb'
10
14
  autoload :Shell, 'jekyll_recker/shell.rb'
15
+ autoload :Site, 'jekyll_recker/site.rb'
11
16
  autoload :Social, 'jekyll_recker/social.rb'
12
17
  autoload :VERSION, 'jekyll_recker/version.rb'
13
18
 
@@ -5,7 +5,7 @@ module JekyllRecker
5
5
  module Commands
6
6
  # Share Command
7
7
  class Share < Jekyll::Command
8
- include Mixins::Logging
8
+ include Logging
9
9
 
10
10
  def self.init_with_program(prog)
11
11
  prog.command(:share) do |c|
@@ -17,7 +17,7 @@ module JekyllRecker
17
17
  end
18
18
 
19
19
  def self.action(args, options)
20
- site = Jekyll::Site.new(configuration_from_options(options))
20
+ site = ::Jekyll::Site.new(configuration_from_options(options))
21
21
  site.reset
22
22
  site.read
23
23
  Social.action(site, args, options)
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JekyllRecker
4
+ # Date Module
5
+ module Date
6
+ def slice_by_consecutive(dates)
7
+ dates.slice_when { |p, c| c != p - 1 && c != p + 1 }.to_a
8
+ end
9
+
10
+ def calculate_streaks(dates)
11
+ slice_by_consecutive(dates).map do |pair|
12
+ first, last = pair.minmax
13
+ {
14
+ 'days' => (last - first).to_i,
15
+ 'start' => first,
16
+ 'end' => last
17
+ }
18
+ end
19
+ end
20
+
21
+ def time_to_date(time)
22
+ ::Date.parse(time.strftime('%Y-%m-%d'))
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JekyllRecker
4
+ # Entry
5
+ class Entry
6
+ include Date
7
+ include Filters
8
+
9
+ def initialize(doc)
10
+ @doc = doc
11
+ end
12
+
13
+ def content
14
+ @doc.content
15
+ end
16
+
17
+ def date
18
+ @date ||= time_to_date(@doc.date)
19
+ end
20
+
21
+ def title
22
+ uyd_date(date)
23
+ end
24
+
25
+ def subtitle
26
+ @doc.data['title']
27
+ end
28
+
29
+ def url
30
+ @doc.url
31
+ end
32
+
33
+ def words
34
+ content.split.map do |token|
35
+ token.gsub!(/[^0-9a-z ']/i, '')
36
+ token.downcase
37
+ end
38
+ end
39
+
40
+ def word_count
41
+ @word_count ||= words.size
42
+ end
43
+ end
44
+ end
@@ -3,12 +3,10 @@
3
3
  module JekyllRecker
4
4
  # Filters
5
5
  module Filters
6
- # Converts a date object to standard Uhh Yeah Dude format.
7
6
  def uyd_date(date)
8
- date.strftime('%A, %B %d %Y')
7
+ date.strftime('%A, %B %-d %Y')
9
8
  end
10
9
 
11
- # Adds commas to a number
12
10
  def pretty(num)
13
11
  num.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse
14
12
  end
@@ -1,214 +1,133 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'fastimage'
4
- require 'mini_magick'
5
-
6
3
  module JekyllRecker
4
+ # Generators Module
7
5
  module Generators
8
- # Image Resize Generator
9
- class ImageResize < Jekyll::Generator
10
- include Mixins::Logging
6
+ # Base Generator
7
+ module Base
8
+ include Date
9
+ include Logging
10
+ include Math
11
11
 
12
- def generate(site)
13
- @site = site
14
- logger.info 'checking images'
15
- resizeable_images.each do |f, d|
16
- logger.info "resizing #{f} to fit #{d}"
17
- image = MiniMagick::Image.new(f)
18
- image.resize d
19
- end
20
- end
12
+ attr_reader :site
21
13
 
22
- def image?(file)
23
- ['.jpg', 'jpeg', '.png', '.svg'].include? File.extname(file)
14
+ def name
15
+ self.class.name.split('::').last.downcase
24
16
  end
25
17
 
26
- def too_big?(width, height)
27
- width > 800 || height > 800
28
- end
29
-
30
- def images
31
- @site.static_files.collect(&:path).select { |f| image?(f) }
18
+ def generate(site)
19
+ @site = Site.new(site)
20
+ if @site.production?
21
+ info "skipping #{name} generator"
22
+ else
23
+ info "running #{name} generator"
24
+ data = crunch
25
+ File.open(data_file_target, 'w') { |f| f.write(JSON.pretty_generate(data)) } unless data.nil?
26
+ end
32
27
  end
33
28
 
34
- def resizeable_images
35
- with_sizes = images.map { |f| [f, FastImage.size(f)].flatten }
36
- with_sizes.select! { |f| too_big?(f[1], f[2]) }
37
- with_sizes.map do |f, w, h|
38
- dimensions = if w > h
39
- '800x600'
40
- else
41
- '600x800'
42
- end
43
- [f, dimensions]
44
- end
29
+ def data_file_target
30
+ File.join site.data_dir, "#{name}.json"
45
31
  end
46
32
  end
47
33
 
48
- # Stats Module
49
- #
50
- # Functions for stats generators.
51
- # @abstract
52
- module Stats
53
- include Mixins::Logging
54
- include Jekyll::Filters
34
+ # Stats Generator
35
+ class Stats < Jekyll::Generator
36
+ include Base
55
37
 
56
- def key
57
- self.class.const_get(:KEY)
58
- end
38
+ attr_reader :site
59
39
 
60
- def generate(site)
61
- @site = site
62
- logger.info "crunching stats.#{key}"
63
- @site.data['stats'] ||= {}
64
- @site.data['stats'][key] = crunch
40
+ def crunch
41
+ generate_stats
65
42
  end
66
43
 
67
- def crunch
68
- raise NotImplementedError, '#crunch not implemented!'
44
+ def generate_stats
45
+ {
46
+ 'total_words' => total(site.word_counts),
47
+ 'average_words' => average(site.word_counts),
48
+ 'total_posts' => site.entries.size,
49
+ 'consecutive_posts' => calculate_streaks(site.dates).first['days'],
50
+ 'swears' => calculate_swears
51
+ }
69
52
  end
70
53
 
71
- # Calculates the average of a list of numbers.
72
- #
73
- # @param [Array<Numeric>] numlist list of numbers to be averaged.
74
- # @return [Numeric] rounded, calculated average of numlist.
75
- def average(numlist)
76
- calc = numlist.inject { |sum, el| sum + el }.to_f / numlist.size
77
- calc.round
54
+ private
55
+
56
+ def calculate_swears
57
+ results = Hash[count_swears]
58
+ results['total'] = total(results.values)
59
+ results
78
60
  end
79
61
 
80
- # Calculates the total of a list of numbers.
81
- #
82
- # @param [Array<Numeric>] numlist list of numbers to be totaled.
83
- # @return [Numeric] calculated total of numlist.
84
- def total(numlist)
85
- numlist.inject(0) { |sum, x| sum + x }
62
+ def count_swears
63
+ occurences(swears, site.words).reject { |_k, v| v.zero? }.sort_by { |_k, v| -v }
86
64
  end
87
65
 
88
- def entries
89
- @site.posts.docs.select(&:published?)
66
+ def swears
67
+ site.recker_config.fetch('swears', [])
90
68
  end
91
69
  end
92
70
 
93
- # Post Count Generator
94
- class PostCount < Jekyll::Generator
95
- include Stats
96
-
97
- KEY = 'posts'
71
+ # Graphs Generator
72
+ class Graphs < Jekyll::Generator
73
+ include Base
98
74
 
99
75
  def crunch
100
- entries.count
76
+ JekyllRecker::Graphs.generate_graphs(site)
77
+ nil
101
78
  end
102
79
  end
103
80
 
104
- # Word Count Generator
105
- class Words < Jekyll::Generator
106
- include Stats
107
-
108
- KEY = 'words'
81
+ # Git Generator
82
+ class Git < Jekyll::Generator
83
+ include Base
109
84
 
110
85
  def crunch
111
- total_counts = entries.collect(&:content).map { |c| number_of_words(c) }
112
86
  {
113
- 'average' => average(total_counts),
114
- 'total' => total(total_counts)
87
+ 'commit_count' => Shell.run('git rev-list --count master').chomp
115
88
  }
116
89
  end
117
90
  end
118
91
 
119
- # Streak Count Generator
120
- class Streaks < Jekyll::Generator
121
- include Stats
122
-
123
- KEY = 'days'
92
+ # Image Resize Generator
93
+ class ImageResize < Jekyll::Generator
94
+ include Base
124
95
 
125
96
  def crunch
126
- streaks.take(1).map do |count, dates|
127
- {
128
- 'days' => count,
129
- 'start' => dates[0],
130
- 'end' => dates[1]
131
- }
132
- end.first
133
- end
134
-
135
- private
136
-
137
- def streaks
138
- _streaks = []
139
- entry_dates.slice_when do |prev, curr|
140
- curr != prev - 1
141
- end.each do |dates|
142
- first, last = dates.minmax
143
- _streaks << [(last - first).to_i, [first, last]]
97
+ load_deps!
98
+ info 'checking images'
99
+ resizeable_images.each do |f, d|
100
+ info "resizing #{f} to fit #{d}"
101
+ image = MiniMagick::Image.new(f)
102
+ image.resize d
144
103
  end
145
- _streaks
104
+ nil
146
105
  end
147
106
 
148
- def entry_dates
149
- entries.collect(&:date).map { |t| Date.new(t.year, t.month, t.day) }.sort.reverse
107
+ def too_big?(width, height)
108
+ width > 800 || height > 800
150
109
  end
151
- end
152
-
153
- # Swear Count Generator
154
- class Swears < Jekyll::Generator
155
- include Stats
156
110
 
157
- KEY = 'swears'
158
-
159
- def crunch
160
- results = Hash.new(0)
161
- entries.collect(&:content).map(&:split).each do |words|
162
- words = words.map(&:downcase)
163
- swears.each do |swear|
164
- count = words.count(swear)
165
- results[swear] += count
166
- end
167
- end
168
- results.reject { |_k, v| v.zero? }.sort_by { |_k, v| -v }
111
+ def load_deps!
112
+ require 'fastimage'
113
+ require 'mini_magick'
169
114
  end
170
115
 
171
- private
172
-
173
- def swears
174
- [
175
- 'ass',
176
- 'asshole',
177
- 'booger',
178
- 'crap',
179
- 'damn',
180
- 'fart',
181
- 'fuck',
182
- 'hell',
183
- 'jackass',
184
- 'piss',
185
- 'poop',
186
- 'shit',
187
- ]
116
+ def images_without_graphs
117
+ site.images.reject { |i| i.include?('/graphs/') }
188
118
  end
189
- end
190
-
191
- # Memory Size Generator
192
- class Memory < Jekyll::Generator
193
- include Stats
194
-
195
- KEY = 'memory'
196
119
 
197
- def crunch
198
- results = Hash.new(0)
199
- entries.each do |entry|
200
- results['chars'] += entry.content.size
201
- results['spaces'] += entry.content.count(' ')
202
- results['size'] += entry.content.bytes.to_a.length
120
+ def resizeable_images
121
+ with_sizes = images_without_graphs.map { |f| [f, FastImage.size(f)].flatten }
122
+ with_sizes.select! { |f| too_big?(f[1], f[2]) }
123
+ with_sizes.map do |f, w, h|
124
+ dimensions = if w > h
125
+ '800x600'
126
+ else
127
+ '600x800'
128
+ end
129
+ [f, dimensions]
203
130
  end
204
- results['size'] = bytes_to_megabytes(results['size'])
205
- results
206
- end
207
-
208
- private
209
-
210
- def bytes_to_megabytes(bytes)
211
- (bytes / (1024.0 * 1024.0)).to_f.round(4)
212
131
  end
213
132
  end
214
133
  end
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler'
4
+
5
+ module JekyllRecker
6
+ # Graphs module
7
+ module Graphs
8
+ def self.generate_graphs(site)
9
+ require 'gruff'
10
+ WordCount.new(site).write
11
+ Swears.new(site).write
12
+ end
13
+
14
+ # Base Graph
15
+ module Base
16
+ attr_reader :site
17
+
18
+ def graphs_join(path)
19
+ File.join Bundler.root, @graphs_dir, path
20
+ end
21
+ end
22
+
23
+ # Word Count Graph
24
+ class WordCount
25
+ include Base
26
+
27
+ def initialize(site)
28
+ @site = site
29
+ @graphs_dir = site.graphs_dir
30
+ end
31
+
32
+ def posts
33
+ site.entries[0..6].reverse
34
+ end
35
+
36
+ def word_counts
37
+ site.word_counts[0..6].reverse
38
+ end
39
+
40
+ def title
41
+ format = '%m/%d/%y'
42
+ first = posts.first.date.strftime(format)
43
+ last = posts.last.date.strftime(format)
44
+ "Word Count: #{first} - #{last}"
45
+ end
46
+
47
+ def labels
48
+ Hash[posts.each_with_index.map { |p, i| [i, p.date.strftime('%a')] }]
49
+ end
50
+
51
+ def write
52
+ g = ::Gruff::Line.new('800x600')
53
+ g.theme = Gruff::Themes::PASTEL
54
+ g.hide_legend = true
55
+ g.labels = labels
56
+ g.data :words, word_counts
57
+ g.title = title
58
+ g.x_axis_label = 'Day'
59
+ g.y_axis_label = 'Word Count'
60
+ g.minimum_value = 0
61
+ g.write(graphs_join('words.png'))
62
+ end
63
+ end
64
+
65
+ # Swears Chart
66
+ class Swears
67
+ include Base
68
+
69
+ def initialize(site)
70
+ @data_dir = site.data_dir
71
+ @graphs_dir = site.graphs_dir
72
+ end
73
+
74
+ def results
75
+ path = File.join(@data_dir, 'stats.json')
76
+ data = JSON.parse(File.read(path))['swears']
77
+ data.delete('total')
78
+ data
79
+ end
80
+
81
+ def write
82
+ g = ::Gruff::Pie.new('800x600')
83
+ g.theme = Gruff::Themes::PASTEL
84
+ g.hide_legend = false
85
+ g.legend_at_bottom = true
86
+ g.minimum_value = 0
87
+ results.each { |w, n| g.data w, n }
88
+ g.write(graphs_join('swears.png'))
89
+ end
90
+ end
91
+ end
92
+ end