jekyll-recker 1.12.0 → 2.2.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 +4 -4
- data/lib/jekyll-recker.rb +6 -1
- data/lib/jekyll_recker/commands.rb +2 -2
- data/lib/jekyll_recker/date.rb +21 -0
- data/lib/jekyll_recker/entry.rb +29 -0
- data/lib/jekyll_recker/filters.rb +0 -2
- data/lib/jekyll_recker/generators.rb +77 -118
- data/lib/jekyll_recker/generators/image_resize.rb +58 -0
- data/lib/jekyll_recker/graphs.rb +79 -0
- data/lib/jekyll_recker/logging.rb +19 -0
- data/lib/jekyll_recker/math.rb +15 -0
- data/lib/jekyll_recker/site.rb +24 -0
- data/lib/jekyll_recker/social.rb +10 -12
- data/lib/jekyll_recker/tags.rb +5 -4
- data/lib/jekyll_recker/version.rb +1 -1
- metadata +10 -155
- data/LICENSE +0 -674
- data/README.md +0 -105
- data/_includes/figure.html +0 -14
- data/_includes/footer.html +0 -14
- data/_includes/head.html +0 -21
- data/_includes/header.html +0 -4
- data/_includes/nav.html +0 -5
- data/_includes/pager.html +0 -13
- data/_layouts/home.html +0 -13
- data/_layouts/page.html +0 -13
- data/_layouts/post.html +0 -20
- data/lib/jekyll_recker/mixins.rb +0 -40
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ea539028f1189e2337f3303c646c14a6c479c9a8bc4345e095b4807c6cbc78f0
|
4
|
+
data.tar.gz: 54890ff14bc9a52cecf154b1af2f44b64a4536a19c270e7bc741bb5f8be1436f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f7907b88a8fdf1ceb6cdc8f57042b6cc1424ff09a243f50b6790953ab591b625489e656f5ac35e63f3b2760b6ec5d5e659e0fd6ee19de3d7b3b0ef839d0cc924
|
7
|
+
data.tar.gz: 31a39ca124631df4a59216b7734d7f6e33419a3ebfcc717d54a6a53334c5eea44be3db6c4eca1cdecf3d361f417bb58ab1af3bb26a71f4b169b054fefb351daa
|
data/lib/jekyll-recker.rb
CHANGED
@@ -6,8 +6,13 @@ require 'jekyll'
|
|
6
6
|
#
|
7
7
|
# The greatest jekyll plugin in the world
|
8
8
|
module JekyllRecker
|
9
|
-
autoload :
|
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
|
|
@@ -0,0 +1,21 @@
|
|
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
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module JekyllRecker
|
4
|
+
# Entry
|
5
|
+
class Entry
|
6
|
+
def initialize(doc)
|
7
|
+
@doc = doc
|
8
|
+
end
|
9
|
+
|
10
|
+
def content
|
11
|
+
@doc.content
|
12
|
+
end
|
13
|
+
|
14
|
+
def date
|
15
|
+
@date ||= ::Date.parse(@doc.date.strftime('%Y-%m-%d'))
|
16
|
+
end
|
17
|
+
|
18
|
+
def words
|
19
|
+
content.split.map do |token|
|
20
|
+
token.gsub!(/[^0-9a-z ]/i, '')
|
21
|
+
token.downcase
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def word_count
|
26
|
+
@word_count ||= words.size
|
27
|
+
end
|
28
|
+
end
|
29
|
+
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
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,153 +1,112 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
4
|
-
require 'fastimage'
|
3
|
+
require 'bundler'
|
5
4
|
|
6
5
|
module JekyllRecker
|
6
|
+
# Generators Module
|
7
7
|
module Generators
|
8
|
-
#
|
9
|
-
|
10
|
-
include
|
8
|
+
# Base Generator Functions
|
9
|
+
module Base
|
10
|
+
include Date
|
11
|
+
include Logging
|
12
|
+
include Math
|
11
13
|
|
12
|
-
def
|
13
|
-
|
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
|
21
|
-
|
22
|
-
def image?(file)
|
23
|
-
['.jpg', 'jpeg', '.png', '.svg'].include? File.extname(file)
|
24
|
-
end
|
25
|
-
|
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) }
|
32
|
-
end
|
33
|
-
|
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
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
# Stats Module
|
49
|
-
#
|
50
|
-
# Functions for stats generators.
|
51
|
-
# @abstract
|
52
|
-
module Stats
|
53
|
-
include Mixins::Logging
|
54
|
-
include Jekyll::Filters
|
55
|
-
|
56
|
-
def key
|
57
|
-
self.class.const_get(:KEY)
|
58
|
-
end
|
59
|
-
|
60
|
-
def generate(site)
|
61
|
-
@site = site
|
62
|
-
logger.info "crunching stats.#{key}"
|
63
|
-
@site.data['stats'] ||= {}
|
64
|
-
@site.data['stats'][key] = crunch
|
14
|
+
def production?
|
15
|
+
ENV['JEKYLL_ENV'] == 'production'
|
65
16
|
end
|
66
17
|
|
67
|
-
def
|
68
|
-
|
18
|
+
def word_counts
|
19
|
+
@word_counts ||= bodies.map(&:split).map(&:size)
|
69
20
|
end
|
70
21
|
|
71
|
-
|
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
|
22
|
+
def words
|
23
|
+
bodies.map(&:split).flatten
|
78
24
|
end
|
79
25
|
|
80
|
-
|
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 }
|
26
|
+
def bodies
|
27
|
+
entries.collect(&:content)
|
86
28
|
end
|
87
29
|
|
88
30
|
def entries
|
89
|
-
@site.posts.docs.select(&:published?)
|
31
|
+
@site.posts.docs.select(&:published?).sort_by(&:date).reverse
|
90
32
|
end
|
91
|
-
end
|
92
|
-
|
93
|
-
# Post Count Generator
|
94
|
-
class PostCount < Jekyll::Generator
|
95
|
-
include Stats
|
96
|
-
|
97
|
-
KEY = 'posts'
|
98
33
|
|
99
|
-
def
|
100
|
-
entries.
|
34
|
+
def dates
|
35
|
+
entries.collect(&:date).map { |t| ::Date.new(t.year, t.month, t.day) }
|
101
36
|
end
|
102
37
|
end
|
103
38
|
|
104
|
-
#
|
105
|
-
class
|
106
|
-
include
|
39
|
+
# Stats Generator
|
40
|
+
class Stats < Jekyll::Generator
|
41
|
+
include Base
|
42
|
+
include Graphs
|
107
43
|
|
108
|
-
|
44
|
+
def generate(site)
|
45
|
+
@site = site
|
46
|
+
logger.info 'calculating statistics'
|
47
|
+
@site.data['stats'] = data
|
48
|
+
if production?
|
49
|
+
logger.info 'production detected. skipping graphs'
|
50
|
+
else
|
51
|
+
require 'gruff'
|
52
|
+
logger.info 'generating graphs'
|
53
|
+
generate_graphs(entries, swear_results, graphs_dir)
|
54
|
+
end
|
55
|
+
end
|
109
56
|
|
110
|
-
def
|
111
|
-
total_counts = entries.collect(&:content).map { |c| number_of_words(c) }
|
57
|
+
def data
|
112
58
|
{
|
113
|
-
'
|
114
|
-
'
|
59
|
+
'total_words' => total(word_counts),
|
60
|
+
'average_words' => average(word_counts),
|
61
|
+
'total_posts' => entries.size,
|
62
|
+
'consecutive_posts' => calculate_streaks(dates).first['days'],
|
63
|
+
'swears' => {
|
64
|
+
'total' => swear_results.map(&:last).reduce(0, :+),
|
65
|
+
'words' => swear_results
|
66
|
+
}
|
115
67
|
}
|
116
68
|
end
|
117
|
-
end
|
118
|
-
|
119
|
-
# Streak Count Generator
|
120
|
-
class Streaks < Jekyll::Generator
|
121
|
-
include Stats
|
122
69
|
|
123
|
-
|
70
|
+
private
|
124
71
|
|
125
|
-
def
|
126
|
-
|
127
|
-
{
|
128
|
-
'days' => count,
|
129
|
-
'start' => dates[0],
|
130
|
-
'end' => dates[1]
|
131
|
-
}
|
132
|
-
end.first
|
72
|
+
def swear_results
|
73
|
+
@swear_results ||= count_swears
|
133
74
|
end
|
134
75
|
|
135
|
-
|
136
|
-
|
137
|
-
|
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]]
|
144
|
-
end
|
145
|
-
_streaks
|
76
|
+
def graphs_dir
|
77
|
+
recker = @site.config.fetch('recker', {})
|
78
|
+
recker.fetch('graphs', 'assets/images/graphs/')
|
146
79
|
end
|
147
80
|
|
148
|
-
def
|
149
|
-
|
81
|
+
def count_swears
|
82
|
+
results = Hash.new(0)
|
83
|
+
bodies.map(&:split).each do |words|
|
84
|
+
words = words.map(&:downcase)
|
85
|
+
swears.each do |swear|
|
86
|
+
count = words.count(swear)
|
87
|
+
results[swear] += count
|
88
|
+
end
|
89
|
+
end
|
90
|
+
results.reject { |_k, v| v.zero? }.sort_by { |_k, v| -v }
|
91
|
+
end
|
92
|
+
|
93
|
+
def swears
|
94
|
+
%w[
|
95
|
+
ass
|
96
|
+
asshole
|
97
|
+
booger
|
98
|
+
crap
|
99
|
+
damn
|
100
|
+
fart
|
101
|
+
fuck
|
102
|
+
hell
|
103
|
+
jackass
|
104
|
+
piss
|
105
|
+
poop
|
106
|
+
shit
|
107
|
+
]
|
150
108
|
end
|
151
109
|
end
|
110
|
+
require 'jekyll_recker/generators/image_resize.rb'
|
152
111
|
end
|
153
112
|
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module JekyllRecker
|
4
|
+
module Generators
|
5
|
+
# Image Resize Generator
|
6
|
+
class ImageResize < Jekyll::Generator
|
7
|
+
include Base
|
8
|
+
|
9
|
+
def generate(site)
|
10
|
+
@site = site
|
11
|
+
if production?
|
12
|
+
logger.info 'production detected, skipping images'
|
13
|
+
return
|
14
|
+
else
|
15
|
+
logger.info 'loading image resizing deps'
|
16
|
+
require 'fastimage'
|
17
|
+
require 'mini_magick'
|
18
|
+
end
|
19
|
+
logger.info 'checking images'
|
20
|
+
resizeable_images.each do |f, d|
|
21
|
+
logger.info "resizing #{f} to fit #{d}"
|
22
|
+
image = MiniMagick::Image.new(f)
|
23
|
+
image.resize d
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def image?(file)
|
28
|
+
['.jpg', 'jpeg', '.png', '.svg'].include? File.extname(file)
|
29
|
+
end
|
30
|
+
|
31
|
+
def too_big?(width, height)
|
32
|
+
width > 800 || height > 800
|
33
|
+
end
|
34
|
+
|
35
|
+
def graph?(file)
|
36
|
+
file.include?('/graphs/')
|
37
|
+
end
|
38
|
+
|
39
|
+
def images
|
40
|
+
@site.static_files.collect(&:path).select { |f| image?(f) }
|
41
|
+
end
|
42
|
+
|
43
|
+
def resizeable_images
|
44
|
+
without_graphs = images.reject { |i| graph?(i) }
|
45
|
+
with_sizes = without_graphs.map { |f| [f, FastImage.size(f)].flatten }
|
46
|
+
with_sizes.select! { |f| too_big?(f[1], f[2]) }
|
47
|
+
with_sizes.map do |f, w, h|
|
48
|
+
dimensions = if w > h
|
49
|
+
'800x600'
|
50
|
+
else
|
51
|
+
'600x800'
|
52
|
+
end
|
53
|
+
[f, dimensions]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler'
|
4
|
+
|
5
|
+
module JekyllRecker
|
6
|
+
# Graphs module
|
7
|
+
module Graphs
|
8
|
+
def generate_graphs(posts, swears, graphs_dir)
|
9
|
+
WordCount.new(posts, graphs_dir).write
|
10
|
+
Swears.new(swears, graphs_dir).write
|
11
|
+
end
|
12
|
+
|
13
|
+
# Word Count Graph
|
14
|
+
class WordCount
|
15
|
+
def initialize(posts, graphs_dir)
|
16
|
+
@posts = posts[0..6].reverse
|
17
|
+
@graphs_dir = graphs_dir
|
18
|
+
end
|
19
|
+
|
20
|
+
def graphs_join(path)
|
21
|
+
File.join Bundler.root, @graphs_dir, path
|
22
|
+
end
|
23
|
+
|
24
|
+
def title
|
25
|
+
format = '%m/%d/%y'
|
26
|
+
first = @posts.first.date.strftime(format)
|
27
|
+
last = @posts.last.date.strftime(format)
|
28
|
+
"Word Count: #{first} - #{last}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def labels
|
32
|
+
Hash[@posts.each_with_index.map { |p, i| [i, p.date.strftime('%a')] }]
|
33
|
+
end
|
34
|
+
|
35
|
+
# TODO: copied from jekyll
|
36
|
+
def number_of_words(input)
|
37
|
+
input.split.length
|
38
|
+
end
|
39
|
+
|
40
|
+
def write
|
41
|
+
g = Gruff::Line.new('800x600')
|
42
|
+
g.theme = Gruff::Themes::PASTEL
|
43
|
+
g.hide_legend = true
|
44
|
+
g.labels = labels
|
45
|
+
g.data :words, @posts.collect(&:content).map { |c| number_of_words(c) }
|
46
|
+
g.title = title
|
47
|
+
g.x_axis_label = 'Day'
|
48
|
+
g.y_axis_label = 'Word Count'
|
49
|
+
g.minimum_value = 0
|
50
|
+
g.write(graphs_join('words.png'))
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Swears Chart
|
55
|
+
class Swears
|
56
|
+
attr_reader :results
|
57
|
+
|
58
|
+
def initialize(results, graphs_dir)
|
59
|
+
@results = results
|
60
|
+
@graphs_dir = graphs_dir
|
61
|
+
end
|
62
|
+
|
63
|
+
# TODO: I SUCK
|
64
|
+
def graphs_join(path)
|
65
|
+
File.join Bundler.root, @graphs_dir, path
|
66
|
+
end
|
67
|
+
|
68
|
+
def write
|
69
|
+
g = Gruff::Pie.new('800x600')
|
70
|
+
g.theme = Gruff::Themes::PASTEL
|
71
|
+
g.hide_legend = false
|
72
|
+
g.legend_at_bottom = true
|
73
|
+
g.minimum_value = 0
|
74
|
+
results.each { |w, n| g.data w, n }
|
75
|
+
g.write(graphs_join('swears.png'))
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|