jekyll-stats 0.2.0 → 0.3.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 +6 -0
- data/README.md +17 -0
- data/lib/jekyll-stats/command.rb +1 -0
- data/lib/jekyll-stats/formatter.rb +14 -0
- data/lib/jekyll-stats/stats_calculator.rb +38 -0
- data/lib/jekyll-stats/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3465b65818c34b7a72b5b76d9bb242a37487837e5639927ae65c7d9a00b9ac62
|
|
4
|
+
data.tar.gz: 9e408de4fcfb55f1581a2b1905018852095cd4ae5c9a4a2f7592e252e24e42b0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bd03f85ad69f529b003a211a7004acdf0a30851f0a2084abab6f3f142a511a620d7c3d4f755f4dcab6abc2286c55bb5f25c7bec610ccf565e0f012e975ba21d7
|
|
7
|
+
data.tar.gz: d42e6b8897070b6529b1cc32f7e6e52c11563e2890bcfdd5c03f4a2237216cb2afb80c62d2ec94489fe6433ffb3706e954d308e31c72a1b4f67fa7a486716ab1
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [0.3.0] - 2026-08-30
|
|
4
|
+
|
|
5
|
+
- Add `internal_links` to stats: posts ranked by inbound links from other posts
|
|
6
|
+
- Source posts can be excluded by tag via `jekyll-stats.link_source_exclude_tags` in `_config.yml`
|
|
7
|
+
- `--json` no longer prints "Loading site..." to stdout, so output pipes cleanly to `jq`
|
|
8
|
+
|
|
3
9
|
## [0.2.0] - 2026-01-03
|
|
4
10
|
|
|
5
11
|
- Add `--tags` / `-t` option to filter stats by tags
|
data/README.md
CHANGED
|
@@ -81,10 +81,27 @@ The `--save` flag writes `_data/stats.json` with this structure:
|
|
|
81
81
|
"posts_by_day_of_week": { "monday": 23, "tuesday": 18, "wednesday": 15, "thursday": 20, "friday": 22, "saturday": 14, "sunday": 15 },
|
|
82
82
|
"tags": [{ "name": "ruby", "count": 34 }, { "name": "opensource", "count": 28 }],
|
|
83
83
|
"categories": [{ "name": "code", "count": 45 }, { "name": "cars", "count": 32 }],
|
|
84
|
+
"internal_links": [
|
|
85
|
+
{ "url": "/2024/01/foo", "title": "Foo", "inbound_count": 7, "inbound_from": ["/2024/03/bar", "/2024/06/baz"] }
|
|
86
|
+
],
|
|
84
87
|
"drafts_count": 3
|
|
85
88
|
}
|
|
86
89
|
```
|
|
87
90
|
|
|
91
|
+
### Internal links
|
|
92
|
+
|
|
93
|
+
`internal_links` lists posts ranked by how many other posts link to them. It matches markdown and `<a href>` links that point at another post's URL, either as a root-relative path or an absolute URL under your site's `url:`. Self-links and duplicate links from the same source post are ignored.
|
|
94
|
+
|
|
95
|
+
To stop link-list style posts (year in review, roundups) inflating the counts, exclude them as sources by tag in `_config.yml`:
|
|
96
|
+
|
|
97
|
+
```yaml
|
|
98
|
+
jekyll-stats:
|
|
99
|
+
link_source_exclude_tags:
|
|
100
|
+
- roundup
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Excluded posts still appear as targets; they just don't contribute outbound links.
|
|
104
|
+
|
|
88
105
|
## Building a Stats Page
|
|
89
106
|
|
|
90
107
|
After running `jekyll stats --save`, create a stats page using Liquid:
|
data/lib/jekyll-stats/command.rb
CHANGED
|
@@ -34,6 +34,11 @@ module JekyllStats
|
|
|
34
34
|
lines << categories_line
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
+
if stats[:internal_links].any?
|
|
38
|
+
lines << ""
|
|
39
|
+
lines << most_linked_posts
|
|
40
|
+
end
|
|
41
|
+
|
|
37
42
|
if stats[:drafts_count].positive?
|
|
38
43
|
lines << ""
|
|
39
44
|
lines << "Drafts: #{stats[:drafts_count]}"
|
|
@@ -99,6 +104,15 @@ module JekyllStats
|
|
|
99
104
|
"Categories:\n #{cat_strs.join(" | ")}"
|
|
100
105
|
end
|
|
101
106
|
|
|
107
|
+
def most_linked_posts
|
|
108
|
+
links = stats[:internal_links].first(5)
|
|
109
|
+
lines = ["Most Linked Posts:"]
|
|
110
|
+
links.each do |l|
|
|
111
|
+
lines << " #{l[:inbound_count].to_s.rjust(2)} #{truncate(l[:title], 50)}"
|
|
112
|
+
end
|
|
113
|
+
lines.join("\n")
|
|
114
|
+
end
|
|
115
|
+
|
|
102
116
|
def format_number(n)
|
|
103
117
|
n.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse
|
|
104
118
|
end
|
|
@@ -40,6 +40,7 @@ module JekyllStats
|
|
|
40
40
|
posts_by_day_of_week: posts_by_day_of_week(posts),
|
|
41
41
|
tags: tag_counts(posts),
|
|
42
42
|
categories: category_counts(posts),
|
|
43
|
+
internal_links: internal_links(posts),
|
|
43
44
|
drafts_count: drafts_count
|
|
44
45
|
}
|
|
45
46
|
end
|
|
@@ -147,6 +148,42 @@ module JekyllStats
|
|
|
147
148
|
.map { |name, count| { name: name, count: count } }
|
|
148
149
|
end
|
|
149
150
|
|
|
151
|
+
def internal_links(posts)
|
|
152
|
+
by_url = posts.each_with_object({}) { |p, h| h[normalize_url(p.url)] = p }
|
|
153
|
+
exclude = Array(site.config.dig("jekyll-stats", "link_source_exclude_tags")).map { |t| normalize_tag(t) }
|
|
154
|
+
site_url = site.config["url"].to_s
|
|
155
|
+
|
|
156
|
+
inbound = Hash.new { |h, k| h[k] = [] }
|
|
157
|
+
posts.each do |post|
|
|
158
|
+
post_tags = (post.data["tags"] || []).map { |t| normalize_tag(t) }
|
|
159
|
+
next if exclude.any? && (exclude & post_tags).any?
|
|
160
|
+
|
|
161
|
+
post.content.to_s.scan(%r{(?:\]\(|<a\s[^>]*href=["'])([^"'\s)]+)}i).flatten.each do |href|
|
|
162
|
+
href = href.delete_prefix(site_url) unless site_url.empty?
|
|
163
|
+
next unless href.start_with?("/")
|
|
164
|
+
|
|
165
|
+
target = by_url[normalize_url(href)]
|
|
166
|
+
next unless target
|
|
167
|
+
next if target == post
|
|
168
|
+
|
|
169
|
+
inbound[target] << post
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
inbound.map { |target, sources|
|
|
174
|
+
{
|
|
175
|
+
url: target.url,
|
|
176
|
+
title: target.data["title"] || "(untitled)",
|
|
177
|
+
inbound_count: sources.uniq.size,
|
|
178
|
+
inbound_from: sources.uniq.map(&:url).sort
|
|
179
|
+
}
|
|
180
|
+
}.sort_by { |r| [-r[:inbound_count], r[:url]] }
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def normalize_url(url)
|
|
184
|
+
url.sub(/[#?].*\z/, "").sub(%r{/index\.html\z}, "").chomp(".html").chomp("/")
|
|
185
|
+
end
|
|
186
|
+
|
|
150
187
|
def drafts_count
|
|
151
188
|
return 0 unless site.respond_to?(:drafts) && site.drafts
|
|
152
189
|
|
|
@@ -171,6 +208,7 @@ module JekyllStats
|
|
|
171
208
|
posts_by_day_of_week: %w[sunday monday tuesday wednesday thursday friday saturday].each_with_object({}) { |d, h| h[d] = 0 },
|
|
172
209
|
tags: [],
|
|
173
210
|
categories: [],
|
|
211
|
+
internal_links: [],
|
|
174
212
|
drafts_count: 0
|
|
175
213
|
}
|
|
176
214
|
end
|
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.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Andrew Nesbitt
|
|
@@ -77,7 +77,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
77
77
|
- !ruby/object:Gem::Version
|
|
78
78
|
version: '0'
|
|
79
79
|
requirements: []
|
|
80
|
-
rubygems_version: 4.0.
|
|
80
|
+
rubygems_version: 4.0.17
|
|
81
81
|
specification_version: 4
|
|
82
82
|
summary: Jekyll plugin that generates site statistics
|
|
83
83
|
test_files: []
|