jekyll-stats 0.1.0 → 0.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/CHANGELOG.md +4 -0
- data/README.md +92 -35
- data/lib/jekyll-stats/command.rb +2 -1
- data/lib/jekyll-stats/stats_calculator.rb +23 -4
- data/lib/jekyll-stats/version.rb +1 -1
- metadata +15 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ab21769c8de5f9ff18a6ad985b0a0240dbf00c29be751b3f0aee27f8c313a257
|
|
4
|
+
data.tar.gz: '071349d927967afb2c9164d9382a56175d9aa106d818ac267d32930169aca4e7'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c1f4bc991fa3230b0e0c3d5c0a471495738a0a853021ba257cc5501cf6748fb8ed567892b0005f5166071c3a2e2aab398380b83fbcb90a11819d2896583957ce
|
|
7
|
+
data.tar.gz: de7e7fc767997a55e345f63df9214fc46501790ff9a3f7fba3ee166968f43ce40ec1fec8ed8f4002a4c39a3c5de95ab6bc06307ecb3881fc19b191466b0fc28c
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
A Jekyll plugin that adds a `jekyll stats` command to display site statistics.
|
|
4
4
|
|
|
5
|
+
[rubygems.org/gems/jekyll-stats](https://rubygems.org/gems/jekyll-stats)
|
|
6
|
+
|
|
5
7
|
## Installation
|
|
6
8
|
|
|
7
9
|
Add to your Jekyll site's Gemfile:
|
|
@@ -28,6 +30,10 @@ jekyll stats --json
|
|
|
28
30
|
|
|
29
31
|
# Include drafts in calculations
|
|
30
32
|
jekyll stats --drafts
|
|
33
|
+
|
|
34
|
+
# Filter by tags (comma-separated, matches posts with ANY of the tags)
|
|
35
|
+
jekyll stats --tags ruby
|
|
36
|
+
jekyll stats -t ruby,rails
|
|
31
37
|
```
|
|
32
38
|
|
|
33
39
|
### Terminal Output
|
|
@@ -89,50 +95,101 @@ layout: page
|
|
|
89
95
|
title: Site Statistics
|
|
90
96
|
---
|
|
91
97
|
|
|
92
|
-
<p>
|
|
93
|
-
<strong>{{ site.data.stats.total_posts }}</strong> posts,
|
|
94
|
-
<strong>{{ site.data.stats.total_words | divided_by: 1000 }}k</strong> words,
|
|
95
|
-
<strong>{{ site.data.stats.reading_minutes | divided_by: 60 }}</strong> hours of reading.
|
|
96
|
-
</p>
|
|
98
|
+
<p>{{ site.data.stats.total_posts }} posts, {{ site.data.stats.total_words }} words, ~{{ site.data.stats.reading_minutes }} minutes reading time.</p>
|
|
97
99
|
|
|
98
|
-
<p>
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
</p>
|
|
100
|
+
<p>Average {{ site.data.stats.average_words }} words per post. Longest: <a href="{{ site.data.stats.longest_post.url }}">{{ site.data.stats.longest_post.title }}</a> ({{ site.data.stats.longest_post.words }} words).</p>
|
|
101
|
+
|
|
102
|
+
<p>First post: {{ site.data.stats.first_post.date }} | Last post: {{ site.data.stats.last_post.date }} | {{ site.data.stats.years_active }} years active.</p>
|
|
102
103
|
|
|
103
104
|
<h2>Posts by Year</h2>
|
|
104
|
-
<
|
|
105
|
+
<table>
|
|
106
|
+
<thead>
|
|
107
|
+
<tr>
|
|
108
|
+
<th style="text-align: left">Year</th>
|
|
109
|
+
<th style="text-align: right">Posts</th>
|
|
110
|
+
</tr>
|
|
111
|
+
</thead>
|
|
112
|
+
<tbody>
|
|
105
113
|
{% for year in site.data.stats.posts_by_year %}
|
|
106
|
-
|
|
114
|
+
<tr>
|
|
115
|
+
<td>{{ year.year }}</td>
|
|
116
|
+
<td style="text-align: right">{{ year.count }}</td>
|
|
117
|
+
</tr>
|
|
107
118
|
{% endfor %}
|
|
108
|
-
</
|
|
119
|
+
</tbody>
|
|
120
|
+
</table>
|
|
109
121
|
|
|
110
122
|
<h2>Top Tags</h2>
|
|
111
|
-
<
|
|
123
|
+
<table>
|
|
124
|
+
<thead>
|
|
125
|
+
<tr>
|
|
126
|
+
<th style="text-align: left">Tag</th>
|
|
127
|
+
<th style="text-align: right">Posts</th>
|
|
128
|
+
</tr>
|
|
129
|
+
</thead>
|
|
130
|
+
<tbody>
|
|
112
131
|
{% for tag in site.data.stats.tags limit:10 %}
|
|
113
|
-
|
|
132
|
+
<tr>
|
|
133
|
+
<td>{{ tag.name }}</td>
|
|
134
|
+
<td style="text-align: right">{{ tag.count }}</td>
|
|
135
|
+
</tr>
|
|
114
136
|
{% endfor %}
|
|
115
|
-
</
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
<
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
137
|
+
</tbody>
|
|
138
|
+
</table>
|
|
139
|
+
|
|
140
|
+
<p><small>Generated {{ site.data.stats.generated_at | date: "%b %d, %Y" }}</small></p>
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Automating Stats Updates
|
|
144
|
+
|
|
145
|
+
You can regenerate stats automatically before each build.
|
|
146
|
+
|
|
147
|
+
### Rake Task
|
|
148
|
+
|
|
149
|
+
```ruby
|
|
150
|
+
# Rakefile
|
|
151
|
+
task :build do
|
|
152
|
+
sh "jekyll stats --save"
|
|
153
|
+
sh "jekyll build"
|
|
154
|
+
end
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### GitHub Actions
|
|
158
|
+
|
|
159
|
+
```yaml
|
|
160
|
+
# .github/workflows/deploy.yml
|
|
161
|
+
jobs:
|
|
162
|
+
build:
|
|
163
|
+
runs-on: ubuntu-latest
|
|
164
|
+
steps:
|
|
165
|
+
- uses: actions/checkout@v4
|
|
166
|
+
- uses: ruby/setup-ruby@v1
|
|
167
|
+
with:
|
|
168
|
+
ruby-version: '3.3'
|
|
169
|
+
bundler-cache: true
|
|
170
|
+
|
|
171
|
+
- name: Generate stats
|
|
172
|
+
run: bundle exec jekyll stats --save
|
|
173
|
+
|
|
174
|
+
- name: Commit stats
|
|
175
|
+
run: |
|
|
176
|
+
git config user.name "github-actions[bot]"
|
|
177
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
178
|
+
git add _data/stats.json
|
|
179
|
+
git diff --staged --quiet || git commit -m "Update site stats"
|
|
180
|
+
git push
|
|
181
|
+
|
|
182
|
+
- name: Build site
|
|
183
|
+
run: bundle exec jekyll build
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Git Pre-commit Hook
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
#!/bin/sh
|
|
190
|
+
# .git/hooks/pre-commit
|
|
191
|
+
bundle exec jekyll stats --save
|
|
192
|
+
git add _data/stats.json
|
|
136
193
|
```
|
|
137
194
|
|
|
138
195
|
## Development
|
data/lib/jekyll-stats/command.rb
CHANGED
|
@@ -13,6 +13,7 @@ module JekyllStats
|
|
|
13
13
|
c.option "save", "--save", "Save stats to _data/stats.json"
|
|
14
14
|
c.option "json", "--json", "Output raw JSON to stdout"
|
|
15
15
|
c.option "drafts", "-D", "--drafts", "Include drafts in calculations"
|
|
16
|
+
c.option "tags", "-t", "--tags TAGS", Array, "Filter stats by tags (comma-separated)"
|
|
16
17
|
c.option "config", "--config CONFIG_FILE[,CONFIG_FILE2,...]", Array, "Custom configuration file"
|
|
17
18
|
c.option "source", "-s", "--source SOURCE", "Custom source directory"
|
|
18
19
|
c.option "destination", "-d", "--destination DESTINATION", "Custom destination directory"
|
|
@@ -31,7 +32,7 @@ module JekyllStats
|
|
|
31
32
|
site.reset
|
|
32
33
|
site.read
|
|
33
34
|
|
|
34
|
-
calculator = StatsCalculator.new(site, include_drafts: options["drafts"])
|
|
35
|
+
calculator = StatsCalculator.new(site, include_drafts: options["drafts"], filter_tags: options["tags"])
|
|
35
36
|
stats = calculator.calculate
|
|
36
37
|
|
|
37
38
|
if options["json"]
|
|
@@ -4,11 +4,12 @@ module JekyllStats
|
|
|
4
4
|
class StatsCalculator
|
|
5
5
|
WORDS_PER_MINUTE = 200
|
|
6
6
|
|
|
7
|
-
attr_reader :site, :include_drafts
|
|
7
|
+
attr_reader :site, :include_drafts, :filter_tags
|
|
8
8
|
|
|
9
|
-
def initialize(site, include_drafts: false)
|
|
9
|
+
def initialize(site, include_drafts: false, filter_tags: nil)
|
|
10
10
|
@site = site
|
|
11
11
|
@include_drafts = include_drafts
|
|
12
|
+
@filter_tags = normalize_filter_tags(filter_tags)
|
|
12
13
|
end
|
|
13
14
|
|
|
14
15
|
def calculate
|
|
@@ -46,9 +47,23 @@ module JekyllStats
|
|
|
46
47
|
def collect_posts
|
|
47
48
|
posts = site.posts.docs.dup
|
|
48
49
|
posts += site.drafts if include_drafts && site.respond_to?(:drafts)
|
|
50
|
+
posts = filter_posts_by_tags(posts) if filter_tags
|
|
49
51
|
posts
|
|
50
52
|
end
|
|
51
53
|
|
|
54
|
+
def filter_posts_by_tags(posts)
|
|
55
|
+
posts.select do |post|
|
|
56
|
+
post_tags = (post.data["tags"] || []).map { |t| normalize_tag(t) }
|
|
57
|
+
(filter_tags & post_tags).any?
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def normalize_filter_tags(tags)
|
|
62
|
+
return nil if tags.nil? || tags.empty?
|
|
63
|
+
|
|
64
|
+
tags.map { |t| normalize_tag(t) }
|
|
65
|
+
end
|
|
66
|
+
|
|
52
67
|
def word_count(post)
|
|
53
68
|
content = post.content.to_s
|
|
54
69
|
text = content.gsub(/<[^>]*>/, " ")
|
|
@@ -112,17 +127,21 @@ module JekyllStats
|
|
|
112
127
|
counts = Hash.new(0)
|
|
113
128
|
posts.each do |post|
|
|
114
129
|
tags = post.data["tags"] || []
|
|
115
|
-
tags.each { |tag| counts[tag] += 1 }
|
|
130
|
+
tags.each { |tag| counts[normalize_tag(tag)] += 1 }
|
|
116
131
|
end
|
|
117
132
|
counts.sort_by { |_, count| -count }
|
|
118
133
|
.map { |name, count| { name: name, count: count } }
|
|
119
134
|
end
|
|
120
135
|
|
|
136
|
+
def normalize_tag(tag)
|
|
137
|
+
tag.to_s.strip.gsub(/[,;:]+\z/, "").strip
|
|
138
|
+
end
|
|
139
|
+
|
|
121
140
|
def category_counts(posts)
|
|
122
141
|
counts = Hash.new(0)
|
|
123
142
|
posts.each do |post|
|
|
124
143
|
categories = post.data["categories"] || []
|
|
125
|
-
categories.each { |cat| counts[cat] += 1 }
|
|
144
|
+
categories.each { |cat| counts[normalize_tag(cat)] += 1 }
|
|
126
145
|
end
|
|
127
146
|
counts.sort_by { |_, count| -count }
|
|
128
147
|
.map { |name, count| { name: name, count: count } }
|
data/lib/jekyll-stats/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: jekyll-stats
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Andrew Nesbitt
|
|
@@ -23,6 +23,20 @@ dependencies:
|
|
|
23
23
|
- - ">="
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
25
|
version: '4.0'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: logger
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '0'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '0'
|
|
26
40
|
description: Adds a 'jekyll stats' command that computes and displays site statistics
|
|
27
41
|
including post counts, word counts, reading times, tag/category distributions, and
|
|
28
42
|
posting frequency.
|