jekyll-archives-dir-category 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 39b0ef05fc29929a7c57609d539ec8fcf34c73c04e2cef76826c1df4525099ea
4
+ data.tar.gz: 4e0e5f70afcf09c9ac93f8b8b22c7261c50b02afeb78a56010cffe41725f3b62
5
+ SHA512:
6
+ metadata.gz: a5696cb3138e9e9334409b162893f6f986297e150efdaf4c0c7d6562960304862f233aea9b340a548029f10e7cbdd3097235bebb6cdeee92e7454cd7509981cf
7
+ data.tar.gz: 23f7a4bc8a87c7acb4043149ab94af2a23e74ed48dc2c86950164278584c58e58cdc022c7df427b2b5b073858ebded565c78e609dcff63fb86a45ef6a0b696e9
@@ -0,0 +1,141 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module Archives
5
+ class Archive < Jekyll::Page
6
+ attr_accessor :posts, :type, :slug
7
+
8
+ # Attributes for Liquid templates
9
+ ATTRIBUTES_FOR_LIQUID = %w(
10
+ posts
11
+ type
12
+ title
13
+ date
14
+ name
15
+ path
16
+ url
17
+ permalink
18
+ ).freeze
19
+
20
+ # Initialize a new Archive page
21
+ #
22
+ # site - The Site object.
23
+ # title - The name of the tag/category or a Hash of the year/month/day in case of date.
24
+ # e.g. { :year => 2014, :month => 08 } or "my-category" or "my-tag".
25
+ # type - The type of archive. Can be one of "year", "month", "day", "category", or "tag"
26
+ # posts - The array of posts that belong in this archive.
27
+ def initialize(site, title, type, posts)
28
+ @site = site
29
+ @posts = posts
30
+ @type = type
31
+ @title = title
32
+ @config = site.config["jekyll-archives-dir-category"]
33
+ @slug = slugify_string_title
34
+
35
+ # Use ".html" for file extension and url for path
36
+ @ext = File.extname(relative_path)
37
+ @path = relative_path
38
+ @name = File.basename(relative_path, @ext)
39
+
40
+ # printf("slug:%s\n", @slug)
41
+ # printf("template:%s\n", template)
42
+ # printf("url_placeholder:%s\n", url_placeholders)
43
+ # printf("url:%s\n", url)
44
+ # printf("path:%s\n", relative_path)
45
+ @data = {
46
+ "layout" => layout,
47
+ }
48
+ @content = ""
49
+ end
50
+
51
+ # The template of the permalink.
52
+ #
53
+ # Returns the template String.
54
+ def template
55
+ @config.dig("permalinks", type)
56
+ end
57
+
58
+ # The layout to use for rendering
59
+ #
60
+ # Returns the layout as a String
61
+ def layout
62
+ @config.dig("layouts", type) || @config["layout"]
63
+ end
64
+
65
+ # Returns a hash of URL placeholder names (as symbols) mapping to the
66
+ # desired placeholder replacements. For details see "url.rb".
67
+ def url_placeholders
68
+ if @title.is_a? Hash
69
+ @title.merge(:type => @type)
70
+ else
71
+ { :name => @slug, :type => @type }
72
+ end
73
+ end
74
+
75
+ # The generated relative url of this page. e.g. /about.html.
76
+ #
77
+ # Returns the String url.
78
+ def url
79
+ @url ||= URL.new(
80
+ :template => template,
81
+ :placeholders => url_placeholders,
82
+ :permalink => nil,
83
+ ).to_s
84
+ rescue ArgumentError
85
+ raise ArgumentError, "Template \"#{template}\" provided is invalid."
86
+ end
87
+
88
+ def permalink
89
+ data&.is_a?(Hash) && data["permalink"]
90
+ end
91
+
92
+ # Produce a title object suitable for Liquid based on type of archive.
93
+ #
94
+ # Returns a String (for tag and category archives) and nil for
95
+ # date-based archives.
96
+ def title
97
+ @title if @title.is_a? String
98
+ end
99
+
100
+ # Produce a date object if a date-based archive
101
+ #
102
+ # Returns a Date.
103
+ def date
104
+ return unless @title.is_a?(Hash)
105
+
106
+ @date ||= begin
107
+ args = @title.values.map(&:to_i)
108
+ Date.new(*args)
109
+ end
110
+ end
111
+
112
+ # Obtain the write path relative to the destination directory
113
+ #
114
+ # Returns the destination relative path String.
115
+ def relative_path
116
+ @relative_path ||= begin
117
+ path = URL.unescape_path(url).gsub(%r!^/!, "")
118
+ path = File.join(path, "index.html") if url.end_with?("/")
119
+ path
120
+ end
121
+ end
122
+
123
+ # Returns the object as a debug String.
124
+ def inspect
125
+ "#<Jekyll:Archive @type=#{@type} @title=#{@title} @data=#{@data.inspect}>"
126
+ end
127
+
128
+ private
129
+
130
+ # Generate slug if @title attribute is a string.
131
+ #
132
+ # Note: mode other than those expected by Jekyll returns the given string after
133
+ # downcasing it.
134
+ def slugify_string_title
135
+ return unless title.is_a?(String)
136
+
137
+ title
138
+ end
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module Archives
5
+ VERSION = "0.1.0"
6
+ end
7
+ end
@@ -0,0 +1,284 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "jekyll"
4
+
5
+ module Jekyll
6
+ module Archives
7
+ # Internal requires
8
+ autoload :Archive, "jekyll-archives-dir-category/archive"
9
+ autoload :VERSION, "jekyll-archives-dir-category/version"
10
+
11
+ class Archives < Jekyll::Generator
12
+ safe true
13
+
14
+ DEFAULTS = {
15
+ "layout" => "archive",
16
+ "enabled" => [],
17
+ "permalinks" => {
18
+ "year" => "/:year/",
19
+ "month" => "/:year/:month/",
20
+ "day" => "/:year/:month/:day/",
21
+ "tag" => "/tag/:name/",
22
+ "category" => "/category/:name/",
23
+ },
24
+ }.freeze
25
+
26
+ def initialize(config = {})
27
+ archives_config = config.fetch("jekyll-archives-dir-category", {})
28
+ printf("Init function of archives\n")
29
+
30
+ if archives_config.is_a?(Hash)
31
+ @config = Utils.deep_merge_hashes(DEFAULTS, archives_config)
32
+ else
33
+ @config = nil
34
+ Jekyll.logger.warn "Archives:", "Expected a hash but got #{archives_config.inspect}"
35
+ Jekyll.logger.warn "", "Archives will not be generated for this site."
36
+ end
37
+ @enabled = @config && @config["enabled"]
38
+ end
39
+
40
+ def generate(site)
41
+ return if @config.nil?
42
+
43
+ @site = site
44
+ @posts = site.posts
45
+ @archives = []
46
+
47
+ @site.config["jekyll-archives-dir-category"] = @config
48
+
49
+ # reset category info for all posts
50
+ reset_posts_category(site)
51
+
52
+ read
53
+ @site.pages.concat(@archives)
54
+
55
+ @site.config["archives"] = @archives
56
+ end
57
+
58
+ # get a category name from '_category.yml'
59
+ # return the category name from path if '_category.yml' not exist
60
+ def get_category_name(path)
61
+ catname = ""
62
+
63
+ curdir = path
64
+ while !curdir.eql?("_posts")
65
+ catpath = curdir + "/_category.yml"
66
+ n = File.basename(curdir)
67
+ if File.exists?(catpath)
68
+ category_info = YAML.load_file(catpath)
69
+ n = category_info["name"] if !category_info["name"].nil?
70
+ end
71
+ catname = n + "/" + catname
72
+ curdir = File.dirname(curdir)
73
+ end
74
+ return catname.slice(0..-2)
75
+ end
76
+
77
+ # Reset category info for all posts
78
+ # Add categories info to site.data["category-info"]
79
+ #
80
+ # the category's href is the path from '_posts' to the file name
81
+ # the category's name is the info in '_category.yml' file
82
+ def reset_posts_category(site)
83
+ post_paths = []
84
+ for p in site.posts.docs
85
+ path = File.dirname(p.path)
86
+ pos = path.index("_posts/")
87
+ path = path[pos..-1]
88
+ post_paths << path
89
+
90
+ c = path[7..-1]
91
+ cn = get_category_name(path)
92
+ p.data["category"] = c
93
+ p.data["categories"] = [c]
94
+ p.data["category-name"] = cn
95
+ p.data["update-time"] = File.mtime(p.path)
96
+ # printf(" category:%s\n", c)
97
+ # printf(" category name:%s\n\n", cn)
98
+ end
99
+ # printf("paths:%s\n", post_paths)
100
+ info = get_category_info("_posts", post_paths)
101
+ category_info = []
102
+ for c in info["subs"]
103
+ category_info << c
104
+ end
105
+ site.data["category-info"] = category_info
106
+ end
107
+
108
+ # the category info from '_category.yml' file
109
+ # this is a recursive function
110
+ def get_category_info(dir_path, paths)
111
+ dir = Dir.new(dir_path)
112
+ info = {
113
+ "href" => dir_path.slice(7..-1),
114
+ "name" => File.basename(dir_path),
115
+ "priority" => 0,
116
+ "subs" => [],
117
+ }
118
+
119
+ if paths.find { |a| a.include?(dir_path) }.nil?
120
+ return nil
121
+ end
122
+
123
+ info_path = dir_path + "/_category.yml"
124
+ if File.exists?(info_path)
125
+ category_info = YAML.load_file(info_path)
126
+ info["name"] = category_info["name"] if !category_info["name"].nil?
127
+ info["priority"] = category_info["priority"] if !category_info["priority"].nil?
128
+ end
129
+ if info["href"].nil?
130
+ info["count"] = 0
131
+ else
132
+ info["count"] = @posts.docs.count { |a|
133
+ a.data["category"].start_with? info["href"]
134
+ }
135
+ end
136
+
137
+ dir.children.each do |file_name|
138
+ file_path = File.join(dir_path, file_name)
139
+ if File.directory?(file_path)
140
+ subinfo = get_category_info(file_path, paths)
141
+ if !subinfo.nil?
142
+ info["subs"] << subinfo
143
+ end
144
+ end
145
+ end
146
+ info["subs"] = info["subs"].sort_by { |a| a["priority"] }
147
+ return info
148
+ end
149
+
150
+ # DEBUG: print category info
151
+ def print_category(c, indent)
152
+ printf("%sname:%s\n", " " * indent, c["name"])
153
+ printf("%shref:%s\n", " " * indent, c["href"])
154
+ printf("%spriority:%s\n\n", " " * indent, c["priority"])
155
+
156
+ for cs in c["subs"]
157
+ if !cs.nil?
158
+ print_category(cs, indent + 4)
159
+ end
160
+ end
161
+ end
162
+
163
+ # DEBUG: print category info
164
+ def dump_category_info(site)
165
+ printf("====================================================\n")
166
+ printf("info:%s\n", site.data["category-info"])
167
+ printf("====================================================\n")
168
+
169
+ for c in site.data["category-info"]
170
+ if !c.nil?
171
+ print_category(c, 1)
172
+ end
173
+ end
174
+ end
175
+
176
+ # Read archive data from posts
177
+ def read
178
+ read_tags
179
+ read_categories
180
+ read_dates
181
+ end
182
+
183
+ def read_tags
184
+ if enabled? "tags"
185
+ tags.each do |title, posts|
186
+ @archives << Archive.new(@site, title, "tag", posts)
187
+ end
188
+ end
189
+ end
190
+
191
+ def read_categories
192
+ if enabled? "categories"
193
+ cats = []
194
+ @site.categories.each { |title, posts_not_used|
195
+ cat = ""
196
+ title.split("/").each { |item|
197
+ if cat == ""
198
+ cat = item
199
+ else
200
+ cat = cat + "/" + item
201
+ end
202
+ cats << cat
203
+ }
204
+ }
205
+ cats = cats.uniq
206
+ for c in cats
207
+ tmp_posts = []
208
+ for post in @site.posts.docs
209
+ # printf("message in plugin\n")
210
+ if post.data["category"] && post.data["category"].start_with?(c)
211
+ tmp_posts << post
212
+ end
213
+ end
214
+ # printf("category:%s post count:%d\n", title, tmp_posts.size)
215
+ @archives << Archive.new(@site, c, "category", tmp_posts)
216
+ end
217
+ end
218
+ end
219
+
220
+ def read_dates
221
+ years.each do |year, y_posts|
222
+ append_enabled_date_type({ :year => year }, "year", y_posts)
223
+ months(y_posts).each do |month, m_posts|
224
+ append_enabled_date_type({ :year => year, :month => month }, "month", m_posts)
225
+ days(m_posts).each do |day, d_posts|
226
+ append_enabled_date_type({ :year => year, :month => month, :day => day }, "day", d_posts)
227
+ end
228
+ end
229
+ end
230
+ end
231
+
232
+ # Checks if archive type is enabled in config
233
+ def enabled?(archive)
234
+ @enabled == true || @enabled == "all" || (@enabled.is_a?(Array) && @enabled.include?(archive))
235
+ end
236
+
237
+ def tags
238
+ @site.tags
239
+ end
240
+
241
+ def categories
242
+ @site.categories
243
+ end
244
+
245
+ # Custom `post_attr_hash` method for years
246
+ def years
247
+ date_attr_hash(@posts.docs, "%Y")
248
+ end
249
+
250
+ # Custom `post_attr_hash` method for months
251
+ def months(year_posts)
252
+ date_attr_hash(year_posts, "%m")
253
+ end
254
+
255
+ # Custom `post_attr_hash` method for days
256
+ def days(month_posts)
257
+ date_attr_hash(month_posts, "%d")
258
+ end
259
+
260
+ private
261
+
262
+ # Initialize a new Archive page and append to base array if the associated date `type`
263
+ # has been enabled by configuration.
264
+ #
265
+ # meta - A Hash of the year / month / day as applicable for date.
266
+ # type - The type of date archive.
267
+ # posts - The array of posts that belong in the date archive.
268
+ def append_enabled_date_type(meta, type, posts)
269
+ @archives << Archive.new(@site, meta, type, posts) if enabled?(type)
270
+ end
271
+
272
+ # Custom `post_attr_hash` for date type archives.
273
+ #
274
+ # posts - Array of posts to be considered for archiving.
275
+ # id - String used to format post date via `Time.strptime` e.g. %Y, %m, etc.
276
+ def date_attr_hash(posts, id)
277
+ hash = Hash.new { |hsh, key| hsh[key] = [] }
278
+ posts.each { |post| hash[post.date.strftime(id)] << post }
279
+ hash.each_value { |posts| posts.sort!.reverse! }
280
+ hash
281
+ end
282
+ end
283
+ end
284
+ end
metadata ADDED
@@ -0,0 +1,149 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jekyll-archives-dir-category
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Alfred Xing
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-09-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: jekyll
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '3.6'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '5.0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '3.6'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '5.0'
33
+ - !ruby/object:Gem::Dependency
34
+ name: bundler
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: minitest
49
+ requirement: !ruby/object:Gem::Requirement
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
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: rake
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: rdoc
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ - !ruby/object:Gem::Dependency
90
+ name: rubocop-jekyll
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '0.9'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '0.9'
103
+ - !ruby/object:Gem::Dependency
104
+ name: shoulda
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ description: Automatically generate post archives by dates, tags, and categories.
118
+ email:
119
+ executables: []
120
+ extensions: []
121
+ extra_rdoc_files: []
122
+ files:
123
+ - lib/jekyll-archives-dir-category.rb
124
+ - lib/jekyll-archives-dir-category/archive.rb
125
+ - lib/jekyll-archives-dir-category/version.rb
126
+ homepage: https://github.com/bijianing/jekyll-archives-dir-category
127
+ licenses:
128
+ - MIT
129
+ metadata: {}
130
+ post_install_message:
131
+ rdoc_options: []
132
+ require_paths:
133
+ - lib
134
+ required_ruby_version: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: 2.3.0
139
+ required_rubygems_version: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - ">="
142
+ - !ruby/object:Gem::Version
143
+ version: '0'
144
+ requirements: []
145
+ rubygems_version: 3.1.6
146
+ signing_key:
147
+ specification_version: 4
148
+ summary: Post archives for Jekyll.
149
+ test_files: []