jekyll-archives-v2 0.0.1

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: bd3853c2320099f7c356af52603b8cbcbe353a220a5b3f59ae5a4a54c087d9ec
4
+ data.tar.gz: 77a4dbb8bb3342964b79b224767c8d43805ad6640c2af2114ac826bc5645f9ec
5
+ SHA512:
6
+ metadata.gz: a25f649119ae3f1d982dfb41898af49c2898793b9057a8c45c64aaee20450d68e6002dcea3964bb46bb42372f381dd5497f205015884174d74ce33ca2cd7d6fb
7
+ data.tar.gz: 7c9fae3f1f46bd596d301337d2680210de53d797f07f22200ac5cb0737de183908686d2c2b897378406bde1499f9298ffacd2b51919f75300f0b412daf89fcd4
@@ -0,0 +1,144 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module ArchivesV2
5
+ class Archive < Jekyll::Page
6
+ attr_accessor :collection_name, :documents, :type, :slug
7
+
8
+ # Attributes for Liquid templates
9
+ ATTRIBUTES_FOR_LIQUID = %w(
10
+ collection_name
11
+ documents
12
+ type
13
+ title
14
+ date
15
+ name
16
+ path
17
+ url
18
+ permalink
19
+ ).freeze
20
+
21
+ # Initialize a new Archive page
22
+ #
23
+ # site - The Site object.
24
+ # title - The name of the tag/category or a Hash of the year/month/day in case of date.
25
+ # e.g. { :year => 2014, :month => 08 } or "my-category" or "my-tag".
26
+ # type - The type of archive. Can be one of "year", "month", "day", "category", or "tag"
27
+ # collection_name - The name of the collection.
28
+ # documents - The array of documents that belong in this archive.
29
+ def initialize(site, title, type, collection_name, documents)
30
+ @site = site
31
+ @documents = documents
32
+ @type = type
33
+ @title = title
34
+ @collection_name = collection_name
35
+ @config = site.config["jekyll-archives"][collection_name]
36
+ @slug = slugify_string_title
37
+
38
+ # Use ".html" for file extension and url for path
39
+ @ext = File.extname(relative_path)
40
+ @path = relative_path
41
+ @name = File.basename(relative_path, @ext)
42
+
43
+ @data = {
44
+ "layout" => layout,
45
+ }
46
+ @content = ""
47
+ end
48
+
49
+ # The template of the permalink.
50
+ #
51
+ # Returns the template String.
52
+ def template
53
+ @config.dig("permalinks", type)
54
+ end
55
+
56
+ # The layout to use for rendering
57
+ #
58
+ # Returns the layout as a String
59
+ def layout
60
+ @config.dig("layouts", type) || @config["layout"]
61
+ end
62
+
63
+ # Returns a hash of URL placeholder names (as symbols) mapping to the
64
+ # desired placeholder replacements. For details see "url.rb".
65
+ def url_placeholders
66
+ if @title.is_a? Hash
67
+ @title.merge(:collection => @collection_name, :type => @type)
68
+ else
69
+ { :collection => @collection_name, :name => @slug, :type => @type }
70
+ end
71
+ end
72
+
73
+ # The generated relative url of this page. e.g. /about.html.
74
+ #
75
+ # Returns the String url.
76
+ def url
77
+ @url ||= URL.new(
78
+ :template => template,
79
+ :placeholders => url_placeholders,
80
+ :permalink => nil
81
+ ).to_s
82
+ rescue ArgumentError
83
+ raise ArgumentError, "Template \"#{template}\" provided is invalid."
84
+ end
85
+
86
+ def permalink
87
+ data&.is_a?(Hash) && data["permalink"]
88
+ end
89
+
90
+ # Produce a title object suitable for Liquid based on type of archive.
91
+ #
92
+ # Returns a String (for tag and category archives) and nil for
93
+ # date-based archives.
94
+ def title
95
+ @title if @title.is_a? String
96
+ end
97
+
98
+ # Produce a date object if a date-based archive
99
+ #
100
+ # Returns a Date.
101
+ def date
102
+ return unless @title.is_a?(Hash)
103
+
104
+ @date ||= begin
105
+ args = @title.values.map(&:to_i)
106
+ Date.new(*args)
107
+ end
108
+ end
109
+
110
+ # Obtain the write path relative to the destination directory
111
+ #
112
+ # Returns the destination relative path String.
113
+ def relative_path
114
+ @relative_path ||= begin
115
+ path = URL.unescape_path(url).gsub(%r!^/!, "")
116
+ path = File.join(path, "index.html") if url.end_with?("/")
117
+ path
118
+ end
119
+ end
120
+
121
+ # Returns the object as a debug String.
122
+ def inspect
123
+ "#<Jekyll:Archive @type=#{@type} @title=#{@title} @data=#{@data.inspect}>"
124
+ end
125
+
126
+ # The Liquid representation of this page.
127
+ def to_liquid
128
+ @to_liquid ||= Jekyll::ArchivesV2::PageDrop.new(self)
129
+ end
130
+
131
+ private
132
+
133
+ # Generate slug if @title attribute is a string.
134
+ #
135
+ # Note: mode other than those expected by Jekyll returns the given string after
136
+ # downcasing it.
137
+ def slugify_string_title
138
+ return unless title.is_a?(String)
139
+
140
+ Utils.slugify(title, :mode => @config["slug_mode"])
141
+ end
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module ArchivesV2
5
+ class PageDrop < Jekyll::Drops::Drop
6
+ extend Forwardable
7
+
8
+ mutable false
9
+
10
+ def_delegators :@obj, :posts, :type, :title, :date, :name, :path, :url, :permalink
11
+ private def_delegator :@obj, :data, :fallback_data
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module ArchivesV2
5
+ VERSION = "0.0.1"
6
+ end
7
+ end
@@ -0,0 +1,164 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "jekyll"
4
+
5
+ module Jekyll
6
+ module ArchivesV2
7
+ # Internal requires
8
+ autoload :Archive, "jekyll-archives-v2/archive"
9
+ autoload :PageDrop, "jekyll-archives-v2/page_drop"
10
+ autoload :VERSION, "jekyll-archives-v2/version"
11
+
12
+ class Archives < Jekyll::Generator
13
+ safe true
14
+
15
+ def initialize(config = {})
16
+ defaults = {}
17
+ config.fetch("collections", {}).each do |name, collection|
18
+ defaults[name] = {
19
+ "layout" => "archive",
20
+ "enabled" => [],
21
+ "permalinks" => {
22
+ "year" => "/#{name}/:year/",
23
+ "month" => "/#{name}/:year/:month/",
24
+ "day" => "/#{name}/:year/:month/:day/",
25
+ "tag" => "/#{name}/tag/:name/",
26
+ "category" => "/#{name}/category/:name/",
27
+ },
28
+ }
29
+ end
30
+ defaults.freeze
31
+ archives_config = config.fetch("jekyll-archives", {})
32
+ if archives_config.is_a?(Hash)
33
+ @config = Utils.deep_merge_hashes(defaults, archives_config)
34
+ else
35
+ @config = nil
36
+ Jekyll.logger.warn "Archives:", "Expected a hash but got #{archives_config.inspect}"
37
+ Jekyll.logger.warn "", "Archives will not be generated for this site."
38
+ end
39
+ end
40
+
41
+ def generate(site)
42
+ return if @config.nil?
43
+
44
+ @site = site
45
+ @collections = site.collections
46
+ @archives = []
47
+
48
+ @site.config["jekyll-archives"] = @config
49
+
50
+ # loop through collections keys and read them
51
+ @config.each do |collection_name, collection_config|
52
+ read(collection_name)
53
+ end
54
+
55
+ @site.pages.concat(@archives)
56
+ @site.config["archives"] = @archives
57
+ end
58
+
59
+ # Read archive data from collection
60
+ def read(collection_name)
61
+ if enabled?(collection_name, "tags")
62
+ read_tags(collection_name)
63
+ end
64
+
65
+ if enabled?(collection_name, "categories")
66
+ read_categories(collection_name)
67
+ end
68
+
69
+ if enabled?(collection_name, "year") || enabled?(collection_name, "month") || enabled?(collection_name, "day")
70
+ read_dates(collection_name)
71
+ end
72
+ end
73
+
74
+ def read_tags(collection_name)
75
+ tags(@collections[collection_name]).each do |title, documents|
76
+ @archives << Archive.new(@site, title, "tag", collection_name, documents)
77
+ end
78
+ end
79
+
80
+ def read_categories(collection_name)
81
+ categories(@collections[collection_name]).each do |title, documents|
82
+ @archives << Archive.new(@site, title, "category", collection_name, documents)
83
+ end
84
+ end
85
+
86
+ def read_dates(collection_name)
87
+ years(@collections[collection_name]).each do |year, y_documents|
88
+ append_enabled_date_type({ :year => year }, "year", collection_name, y_posts)
89
+ months(y_documents).each do |month, m_documents|
90
+ append_enabled_date_type({ :year => year, :month => month }, "month", collection_name, m_posts)
91
+ days(m_documents).each do |day, d_documents|
92
+ append_enabled_date_type({ :year => year, :month => month, :day => day }, "day", collection_name, d_posts)
93
+ end
94
+ end
95
+ end
96
+ end
97
+
98
+ # Checks if archive type is enabled in config
99
+ def enabled?(collection_name, archive)
100
+ @enabled == true || @enabled == "all" || (@enabled.is_a?(Array) && @enabled.include?(archive))
101
+ end
102
+
103
+ def tags(documents)
104
+ doc_attr_hash(documents, "tags")
105
+ end
106
+
107
+ def categories(documents)
108
+ doc_attr_hash(documents, "categories")
109
+ end
110
+
111
+ # Custom `post_attr_hash` method for years
112
+ def years(documents)
113
+ date_attr_hash(documents, "%Y")
114
+ end
115
+
116
+ # Custom `post_attr_hash` method for months
117
+ def months(year_documents)
118
+ date_attr_hash(year_documents, "%m")
119
+ end
120
+
121
+ # Custom `post_attr_hash` method for days
122
+ def days(month_documents)
123
+ date_attr_hash(month_documents, "%d")
124
+ end
125
+
126
+ private
127
+
128
+ # Initialize a new Archive page and append to base array if the associated date `type`
129
+ # has been enabled by configuration.
130
+ #
131
+ # meta - A Hash of the year / month / day as applicable for date.
132
+ # type - The type of date archive.
133
+ # collection_name - the name of the collection
134
+ # documents - The array of documents that belong in the date archive.
135
+ def append_enabled_date_type(meta, type, collection_name, documents)
136
+ @archives << Archive.new(@site, meta, type, collection_name, documents) if enabled?(collection_name, type)
137
+ end
138
+
139
+ # Custom `post_attr_hash` for date type archives.
140
+ #
141
+ # documents - Array of documents to be considered for archiving.
142
+ # id - String used to format post date via `Time.strptime` e.g. %Y, %m, etc.
143
+ def date_attr_hash(documents, id)
144
+ hash = Hash.new { |hsh, key| hsh[key] = [] }
145
+ documents.each { |document| hash[document.date.strftime(id)] << document }
146
+ hash.each_value { |documents| documents.sort!.reverse! }
147
+ hash
148
+ end
149
+
150
+ # Custom `post_attr_hash` for any collection.
151
+ #
152
+ # documents - Array of documents to be considered for archiving.
153
+ # doc_attr - The String name of the Document attribute.
154
+ def doc_attr_hash(documents, doc_attr)
155
+ # Build a hash map based on the specified document attribute ( doc_attr =>
156
+ # array of elements from collection ) then sort each array in reverse order.
157
+ hash = Hash.new { |h, key| h[key] = [] }
158
+ documents.docs.each { |document| document.data[doc_attr]&.each { |t| hash[t] << document } }
159
+ hash.each_value { |documents| documents.sort!.reverse! }
160
+ hash
161
+ end
162
+ end
163
+ end
164
+ end
metadata ADDED
@@ -0,0 +1,150 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jekyll-archives-v2
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - George Corrêa de Araújo
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2024-11-29 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 collections archives by dates, tags, and categories.
118
+ email:
119
+ executables: []
120
+ extensions: []
121
+ extra_rdoc_files: []
122
+ files:
123
+ - lib/jekyll-archives-v2/archive.rb
124
+ - lib/jekyll-archives-v2/page_drop.rb
125
+ - lib/jekyll-archives-v2/version.rb
126
+ - lib/jekyll-archives.rb
127
+ homepage: https://github.com/george-gca/jekyll-archives-v2
128
+ licenses:
129
+ - MIT
130
+ metadata: {}
131
+ post_install_message:
132
+ rdoc_options: []
133
+ require_paths:
134
+ - lib
135
+ required_ruby_version: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: 2.3.0
140
+ required_rubygems_version: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ requirements: []
146
+ rubygems_version: 3.4.20
147
+ signing_key:
148
+ specification_version: 4
149
+ summary: Collections archives for Jekyll.
150
+ test_files: []