coffeebrew_jekyll_archives 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +7 -0
- data/LICENSE +21 -0
- data/README.md +626 -0
- data/lib/coffeebrew_jekyll_archives/config.yml +30 -0
- data/lib/coffeebrew_jekyll_archives/generator.rb +95 -0
- data/lib/coffeebrew_jekyll_archives/page.rb +181 -0
- data/lib/coffeebrew_jekyll_archives/validator.rb +97 -0
- data/lib/coffeebrew_jekyll_archives/version.rb +9 -0
- data/lib/coffeebrew_jekyll_archives.rb +11 -0
- metadata +175 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 43b2a4c983a82213e4a7c864e991616436db32853816d4c6fb3ba160b190d01b
|
4
|
+
data.tar.gz: 7547594cf6862c22b962435fdee631e5890609fb2b377a1ac42540e01a7a49fd
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: cee0c42d0a3177f017bc335d1b0156372db4590c76f81122f2d9d6a1838f52317cdc2c9f5acbbbf7d36379904970c18e3c94db72ca01f21602fabb89593cb7ef
|
7
|
+
data.tar.gz: ffdccf2bc5624e70802c2c6b8fbdd0d3402846f4030a8493447182c22d0bbe177a8cab0808dab9ce57d0a818426b5bd38b278c131cac243578f37732722c2112
|
data/CHANGELOG.md
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2023 Coffee Brew Apps
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,626 @@
|
|
1
|
+
# Jekyll Archives Plugin
|
2
|
+
|
3
|
+
A Jekyll plugin to generate site post archives.
|
4
|
+
|
5
|
+
[![Continuous Integration](https://github.com/coffeebrewapps/coffeebrew_jekyll_archives/actions/workflows/ruby.yml/badge.svg)](https://github.com/coffeebrewapps/coffeebrew_jekyll_archives/actions/workflows/ruby.yml) [![Gem Version](https://badge.fury.io/rb/coffeebrew_jekyll_archives.svg)](https://badge.fury.io/rb/coffeebrew_jekyll_archives)
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your site's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'coffeebrew_jekyll_archives'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then add this line to your site's `_config.yml`:
|
16
|
+
|
17
|
+
```yml
|
18
|
+
plugins:
|
19
|
+
- coffeebrew_jekyll_archives
|
20
|
+
```
|
21
|
+
|
22
|
+
Upon building the Jekyll site, the plugin will automatically generate the archive indexes using the following default
|
23
|
+
configuration:
|
24
|
+
|
25
|
+
```yml
|
26
|
+
---
|
27
|
+
archives:
|
28
|
+
navigation:
|
29
|
+
data: "navigation"
|
30
|
+
name: "Archives"
|
31
|
+
before:
|
32
|
+
after:
|
33
|
+
depths: 3
|
34
|
+
title_format:
|
35
|
+
root:
|
36
|
+
type: "string"
|
37
|
+
style: "/"
|
38
|
+
year:
|
39
|
+
type: "date"
|
40
|
+
style: "%Y"
|
41
|
+
month:
|
42
|
+
type: "date"
|
43
|
+
style: "%b, %Y"
|
44
|
+
day:
|
45
|
+
type: "date"
|
46
|
+
style: "%d %b, %Y"
|
47
|
+
root_dir: "/"
|
48
|
+
root_basename: "archives"
|
49
|
+
index_root: "/archives"
|
50
|
+
index_basename: "index"
|
51
|
+
permalink:
|
52
|
+
root: "/:root_dir"
|
53
|
+
year: "/:root_dir/:index_root/:year"
|
54
|
+
month: "/:root_dir/:index_root/:year/:month"
|
55
|
+
day: "/:root_dir/:index_root/:year/:month/:day"
|
56
|
+
```
|
57
|
+
|
58
|
+
An example of the generated directory structure is as such:
|
59
|
+
|
60
|
+
```bash
|
61
|
+
_site/
|
62
|
+
├── archives
|
63
|
+
│ └── 2023
|
64
|
+
│ ├── 03
|
65
|
+
│ │ ├── 30
|
66
|
+
│ │ │ └── index.html
|
67
|
+
│ │ └── index.html
|
68
|
+
│ └── index.html
|
69
|
+
├── archives.html
|
70
|
+
└── index.html
|
71
|
+
```
|
72
|
+
|
73
|
+
## Configuration
|
74
|
+
|
75
|
+
You can override any of the default configuration values above. The plugin will perform a simple validation on your
|
76
|
+
overrides according to these rules:
|
77
|
+
|
78
|
+
### Navigation config
|
79
|
+
|
80
|
+
This tells the plugin how to generate navigation menu.
|
81
|
+
|
82
|
+
| Key | Allowed Value(s) | Default | Remark |
|
83
|
+
| --- | --- | --- | --- |
|
84
|
+
| data | String | navigation | This tells the plugin where in `site.data[]` to get the navigation data. Usually this would be set in `site.data["navigation"]`. |
|
85
|
+
| name | String | Archives | This is the name rendered in the navigation menu item. |
|
86
|
+
| before | String | nil | This tells the plugin before which existing menu item to insert the archives' root index menu item. |
|
87
|
+
| after | String | nil | This tells the plugin after which existing menu item to insert the archives' root index menu item. |
|
88
|
+
|
89
|
+
When `before` and `after` are `nil`, the archives' root index menu item will be appended last.
|
90
|
+
|
91
|
+
If both `before` and `after` are configured, `before` config will be used and `after` will be ignored.
|
92
|
+
|
93
|
+
### Depths config
|
94
|
+
|
95
|
+
This tells the plugin what indexes to generate.
|
96
|
+
|
97
|
+
There are 3 levels of depths:
|
98
|
+
|
99
|
+
| Level | Description |
|
100
|
+
| --- | --- |
|
101
|
+
| 1 | Generate yearly index only |
|
102
|
+
| 2 | Generate yearly and monthly indexes |
|
103
|
+
| 3 | Generate yearly, monthly and daily indexes |
|
104
|
+
|
105
|
+
### Title format config
|
106
|
+
|
107
|
+
This tells the plugin what is the format of the title to be used for the index entries.
|
108
|
+
|
109
|
+
There are 4 titles that can be generated:
|
110
|
+
|
111
|
+
| Level | Description |
|
112
|
+
| --- | --- |
|
113
|
+
| root | This will be used for the root index entry |
|
114
|
+
| year | This will be used for the yearly index entries |
|
115
|
+
| month | This will be used for the monthly index entries |
|
116
|
+
| day | This will be used for the daily index entries |
|
117
|
+
|
118
|
+
For each title format, you can use one of these types:
|
119
|
+
|
120
|
+
| Type | Description |
|
121
|
+
| --- | --- |
|
122
|
+
| string | A string that uses format syntax and use available variables: year, month, day, eg. `Archive of %{year}-%{month}-%{day}` will be interpreted as `Archive of 2023-03-12` |
|
123
|
+
| date | A string that strictly uses Ruby date identifiers, the plugin will call `date.strftime()` on the format string, eg. `%d %b, %Y` will be interpreted as `12 Mar, 2023` |
|
124
|
+
|
125
|
+
### Directory and path config
|
126
|
+
|
127
|
+
This tells the plugin how to create the directory structure and index page file name.
|
128
|
+
|
129
|
+
| Key | Allowed Value(s) | Default | Remark |
|
130
|
+
| --- | --- | --- | --- |
|
131
|
+
| root_dir | String | / | This tells the plugin what is the root directory to create the root index page. |
|
132
|
+
| root_basename | String | archives | This tells the plugin what is the root index page file name, with `.html` as the extension. |
|
133
|
+
| index_root | String | /archives | This tells the plugin what is the root directory for the yearly/monthly/daily index pages to be generated. |
|
134
|
+
| index_basename | String | index | This tells the plugin what is the file name to use for the yearly/monthly/daily index pages, with `.html` as the extension. |
|
135
|
+
|
136
|
+
### Permalink config
|
137
|
+
|
138
|
+
This tells the plugin how to create the directory structure of the yearly/monthly/daily index pages, and the permalink
|
139
|
+
for the index pages will follow the directory structure.
|
140
|
+
|
141
|
+
There are 4 levels of pages that can be generated:
|
142
|
+
|
143
|
+
| Level | Description |
|
144
|
+
| --- | --- |
|
145
|
+
| root | This will be used for the root index entry |
|
146
|
+
| year | This will be used for the yearly index entries |
|
147
|
+
| month | This will be used for the monthly index entries |
|
148
|
+
| day | This will be used for the daily index entries |
|
149
|
+
|
150
|
+
A few placeholders are available to be used in the permalink:
|
151
|
+
|
152
|
+
| Field | Description |
|
153
|
+
| --- | --- |
|
154
|
+
| root_dir | This will be the root directory where the root index page is created. |
|
155
|
+
| index_root | This will be the root directory where the yearly/monthly/daily index pages are created. |
|
156
|
+
| year | This will be the current year of the current index page. If the current page is the root index, then `year` will always be `0001`. |
|
157
|
+
| month | This will be the current month of the current index page. If the current page is a yearly index, then `month` will always be `01`. |
|
158
|
+
| day | This will be the current day of the current index page. If the current page is a yearly or monthly index, then `day` will always be `01`. |
|
159
|
+
|
160
|
+
### Validation
|
161
|
+
|
162
|
+
If the config overrides have invalid structure, keys or values, the plugin will raise a
|
163
|
+
`Jekyll::Errors::InvalidConfigurationError` during build.
|
164
|
+
|
165
|
+
## Layout
|
166
|
+
|
167
|
+
The plugin does not provide a default layout. You will need to create your own layout in `_layouts` and configure the
|
168
|
+
defaults in `_config.yml`:
|
169
|
+
|
170
|
+
```yml
|
171
|
+
---
|
172
|
+
defaults:
|
173
|
+
- scope:
|
174
|
+
type: "archives"
|
175
|
+
values:
|
176
|
+
layout: "archive"
|
177
|
+
permalink: /:path/:basename:output_ext
|
178
|
+
```
|
179
|
+
|
180
|
+
In addition to Jekyll's default page data, you can also use the page data generated by the plugin in the layout:
|
181
|
+
|
182
|
+
| Field | Description |
|
183
|
+
| --- | --- |
|
184
|
+
| dir | The current index page directory. |
|
185
|
+
| sub_pages | The current index page's sub-pages according to the hierarchy of: 1) root, 2) yearly, 3) monthly, 4) daily. If the current page is the daily index page, then there will be no sub-pages. |
|
186
|
+
| root | The root index page absolute url. This is useful if you need to highlight the archives' root navigation menu item while displaying the nested index pages. |
|
187
|
+
| ancestors | The ancestors of the current page. This is useful if you need to render a tree view of the ancestor pages relative to the current page. |
|
188
|
+
| parent | The immediate parent of the current page. |
|
189
|
+
| collection | The posts collection under the current index page, eg. if the current page is a monthly index page, then all the current month's posts will be available. |
|
190
|
+
| title | The title generated for the current page according to the `title_format` config. |
|
191
|
+
| year | The current year of the current index page. If the current page is the root index, then `year` will always be `0001`. |
|
192
|
+
| month | The current month of the current index page. If the current page is a yearly index, then `month` will always be `01`. |
|
193
|
+
| day | The current day of the current index page. If the current page is a yearly or monthly index, then `day` will always be `01`. |
|
194
|
+
|
195
|
+
An example of a layout that is used by the plugin's test cases:
|
196
|
+
|
197
|
+
```html
|
198
|
+
---
|
199
|
+
layout: default
|
200
|
+
---
|
201
|
+
<h1>Archives of {{ page.title }}</h1>
|
202
|
+
<div class="archives">
|
203
|
+
{% for ancestor in page.ancestors %}
|
204
|
+
<ul>
|
205
|
+
<li>
|
206
|
+
<i class="fa-solid fa-calendar-days"></i>
|
207
|
+
<a href="{{ ancestor.url }}">{{ ancestor.title }}</a>
|
208
|
+
</li>
|
209
|
+
{% endfor %}
|
210
|
+
<ul>
|
211
|
+
<li>
|
212
|
+
<i class="fa-solid fa-calendar-days"></i>
|
213
|
+
<a href="{{ page.url }}">{{ page.title }}</a>
|
214
|
+
</li>
|
215
|
+
{% if page.sub_pages.size > 0 %}
|
216
|
+
<ul>
|
217
|
+
{% for sub_page in page.sub_pages %}
|
218
|
+
<li>
|
219
|
+
<i class="fa-solid fa-calendar-days"></i>
|
220
|
+
<a href="{{ sub_page.url }}">{{ sub_page.title }}</a>
|
221
|
+
</li>
|
222
|
+
{% endfor %}
|
223
|
+
</ul>
|
224
|
+
{% else %}
|
225
|
+
<ul>
|
226
|
+
{% for item in page.collection %}
|
227
|
+
<li>
|
228
|
+
<i class="fa-solid fa-file"></i>
|
229
|
+
<a href="{{ item.url }}">{{ item.date | date: "%d %b, %Y" }} - {{ item.title }}</a>
|
230
|
+
</li>
|
231
|
+
{% endfor %}
|
232
|
+
</ul>
|
233
|
+
{% endif %}
|
234
|
+
</ul>
|
235
|
+
{% for ancestor in page.ancestors %}
|
236
|
+
</ul>
|
237
|
+
{% endfor %}
|
238
|
+
</div>
|
239
|
+
```
|
240
|
+
|
241
|
+
The resulting index pages are as such:
|
242
|
+
|
243
|
+
### Root
|
244
|
+
|
245
|
+
Generated at: `_site/archives.html`.
|
246
|
+
|
247
|
+
```html
|
248
|
+
<!DOCTYPE html>
|
249
|
+
<html>
|
250
|
+
<head>
|
251
|
+
<meta charset="utf-8">
|
252
|
+
<title>/</title>
|
253
|
+
</head>
|
254
|
+
<body>
|
255
|
+
<nav>
|
256
|
+
<a href="/">Home</a>
|
257
|
+
<a href="/about.html">About</a>
|
258
|
+
<a href="/articles.html">Articles</a>
|
259
|
+
<a href="/projects.html">Projects</a>
|
260
|
+
<a href="/archives.html">Archives</a>
|
261
|
+
</nav>
|
262
|
+
|
263
|
+
<div class="container">
|
264
|
+
<h1>Archives of /</h1>
|
265
|
+
<div class="archives">
|
266
|
+
<ul>
|
267
|
+
<li>
|
268
|
+
<i class="fa-solid fa-calendar-days"></i>
|
269
|
+
<a href="/archives.html">/</a>
|
270
|
+
</li>
|
271
|
+
<ul>
|
272
|
+
<li>
|
273
|
+
<i class="fa-solid fa-calendar-days"></i>
|
274
|
+
<a href="/archives/2021/index.html">2021</a>
|
275
|
+
</li>
|
276
|
+
<li>
|
277
|
+
<i class="fa-solid fa-calendar-days"></i>
|
278
|
+
<a href="/archives/2022/index.html">2022</a>
|
279
|
+
</li>
|
280
|
+
<li>
|
281
|
+
<i class="fa-solid fa-calendar-days"></i>
|
282
|
+
<a href="/archives/2023/index.html">2023</a>
|
283
|
+
</li>
|
284
|
+
</ul>
|
285
|
+
</ul>
|
286
|
+
</div>
|
287
|
+
</div>
|
288
|
+
</body>
|
289
|
+
</html>
|
290
|
+
```
|
291
|
+
|
292
|
+
### Yearly index
|
293
|
+
|
294
|
+
Generated at: `_site/2021/index.html` for the year of 2021.
|
295
|
+
|
296
|
+
Note: Header and navigation elements omitted for clarity.
|
297
|
+
|
298
|
+
```html
|
299
|
+
<div class="container">
|
300
|
+
<h1>Archives of 2021</h1>
|
301
|
+
<div class="archives">
|
302
|
+
<ul>
|
303
|
+
<li>
|
304
|
+
<i class="fa-solid fa-calendar-days"></i>
|
305
|
+
<a href="/archives.html">/</a>
|
306
|
+
</li>
|
307
|
+
<ul>
|
308
|
+
<li>
|
309
|
+
<i class="fa-solid fa-calendar-days"></i>
|
310
|
+
<a href="/archives/2021/index.html">2021</a>
|
311
|
+
</li>
|
312
|
+
<ul>
|
313
|
+
<li>
|
314
|
+
<i class="fa-solid fa-calendar-days"></i>
|
315
|
+
<a href="/archives/2021/03/index.html">Mar, 2021</a>
|
316
|
+
</li>
|
317
|
+
<li>
|
318
|
+
<i class="fa-solid fa-calendar-days"></i>
|
319
|
+
<a href="/archives/2021/05/index.html">May, 2021</a>
|
320
|
+
</li>
|
321
|
+
</ul>
|
322
|
+
</ul>
|
323
|
+
</ul>
|
324
|
+
</div>
|
325
|
+
</div>
|
326
|
+
```
|
327
|
+
|
328
|
+
### Monthly index
|
329
|
+
|
330
|
+
Generated at: `_site/2021/03/index.html` for the month of March 2021.
|
331
|
+
|
332
|
+
Note: Header and navigation elements omitted for clarity.
|
333
|
+
|
334
|
+
```html
|
335
|
+
<div class="container">
|
336
|
+
<h1>Archives of Mar, 2021</h1>
|
337
|
+
<div class="archives">
|
338
|
+
<ul>
|
339
|
+
<li>
|
340
|
+
<i class="fa-solid fa-calendar-days"></i>
|
341
|
+
<a href="/archives.html">/</a>
|
342
|
+
</li>
|
343
|
+
<ul>
|
344
|
+
<li>
|
345
|
+
<i class="fa-solid fa-calendar-days"></i>
|
346
|
+
<a href="/archives/2021/index.html">2021</a>
|
347
|
+
</li>
|
348
|
+
<ul>
|
349
|
+
<li>
|
350
|
+
<i class="fa-solid fa-calendar-days"></i>
|
351
|
+
<a href="/archives/2021/03/index.html">Mar, 2021</a>
|
352
|
+
</li>
|
353
|
+
<ul>
|
354
|
+
<li>
|
355
|
+
<i class="fa-solid fa-calendar-days"></i>
|
356
|
+
<a href="/archives/2021/03/12/index.html">12 Mar, 2021</a>
|
357
|
+
</li>
|
358
|
+
<li>
|
359
|
+
<i class="fa-solid fa-calendar-days"></i>
|
360
|
+
<a href="/archives/2021/03/28/index.html">28 Mar, 2021</a>
|
361
|
+
</li>
|
362
|
+
</ul>
|
363
|
+
</ul>
|
364
|
+
</ul>
|
365
|
+
</ul>
|
366
|
+
</div>
|
367
|
+
</div>
|
368
|
+
```
|
369
|
+
|
370
|
+
### Daily index
|
371
|
+
|
372
|
+
Generated at: `_site/2021/03/12/index.html` for the day of 12 March 2021.
|
373
|
+
|
374
|
+
Note: Header and navigation elements omitted for clarity.
|
375
|
+
|
376
|
+
```html
|
377
|
+
<div class="container">
|
378
|
+
<h1>Archives of 12 Mar, 2021</h1>
|
379
|
+
<div class="archives">
|
380
|
+
<ul>
|
381
|
+
<li>
|
382
|
+
<i class="fa-solid fa-calendar-days"></i>
|
383
|
+
<a href="/archives.html">/</a>
|
384
|
+
</li>
|
385
|
+
<ul>
|
386
|
+
<li>
|
387
|
+
<i class="fa-solid fa-calendar-days"></i>
|
388
|
+
<a href="/archives/2021/index.html">2021</a>
|
389
|
+
</li>
|
390
|
+
<ul>
|
391
|
+
<li>
|
392
|
+
<i class="fa-solid fa-calendar-days"></i>
|
393
|
+
<a href="/archives/2021/03/index.html">Mar, 2021</a>
|
394
|
+
</li>
|
395
|
+
<ul>
|
396
|
+
<li>
|
397
|
+
<i class="fa-solid fa-calendar-days"></i>
|
398
|
+
<a href="/archives/2021/03/12/index.html">12 Mar, 2021</a>
|
399
|
+
</li>
|
400
|
+
<ul>
|
401
|
+
<li>
|
402
|
+
<i class="fa-solid fa-file"></i>
|
403
|
+
<a href="/2021/03/12/test-post-1.html">12 Mar, 2021 - This is test post 1</a>
|
404
|
+
</li>
|
405
|
+
</ul>
|
406
|
+
</ul>
|
407
|
+
</ul>
|
408
|
+
</ul>
|
409
|
+
</ul>
|
410
|
+
</div>
|
411
|
+
</div>
|
412
|
+
```
|
413
|
+
|
414
|
+
## Contributing
|
415
|
+
|
416
|
+
Contribution to the gem is very much welcome!
|
417
|
+
|
418
|
+
1. Fork it (https://github.com/coffeebrewapps/coffeebrew_jekyll_archives/fork).
|
419
|
+
2. Create your feature branch (`git checkout -b my-new-feature`).
|
420
|
+
3. Make sure you have setup the repo correctly so that you can run RSpec and Rubocop on your changes. Read more under the [Development](#development) section.
|
421
|
+
4. Commit your changes (`git commit -am 'Add some feature'`).
|
422
|
+
5. If you have added something that is worth mentioning in the README, please also update the README.md accordingly and commit the changes.
|
423
|
+
6. Push to the branch (`git push origin my-new-feature`).
|
424
|
+
7. Create a new Pull Request.
|
425
|
+
|
426
|
+
The repo owner will try to respond to a new PR as soon as possible.
|
427
|
+
|
428
|
+
## Development
|
429
|
+
|
430
|
+
We want to provide a robust gem as much as possible for the users, so writing test cases will be required for any new
|
431
|
+
feature.
|
432
|
+
|
433
|
+
If you are contributing to the gem, please make sure you have setup your development environment correctly so that
|
434
|
+
RSpec and Rubocop can run properly.
|
435
|
+
|
436
|
+
1. After forking the repo, go into the repo directory (`cd coffeebrew_jekyll_archives/`).
|
437
|
+
2. Make sure you have the correct Ruby version installed. This gem requires Ruby >= 2.7.0.
|
438
|
+
3. Once you have the correct Ruby version, install the development dependencies (`bundle install`).
|
439
|
+
4. To test that you have everything installed correctly, run the test cases (`bundle exec rspec`).
|
440
|
+
5. You should see all test cases pass successfully.
|
441
|
+
|
442
|
+
### Source directory structure
|
443
|
+
|
444
|
+
All the gem logic lives in the `/lib` directory:
|
445
|
+
|
446
|
+
```bash
|
447
|
+
lib
|
448
|
+
├── coffeebrew_jekyll_archives
|
449
|
+
│ ├── config.yml
|
450
|
+
│ ├── generator.rb
|
451
|
+
│ ├── page.rb
|
452
|
+
│ ├── validator.rb
|
453
|
+
│ └── version.rb
|
454
|
+
└── coffeebrew_jekyll_archives.rb
|
455
|
+
```
|
456
|
+
|
457
|
+
The files that are currently in the repo:
|
458
|
+
|
459
|
+
| File | Description |
|
460
|
+
| --- | --- |
|
461
|
+
| `lib/coffeebrew_jekyll_archives/config.yml` | This contains the default configuration for the plugin to generate the archive indexes. |
|
462
|
+
| `lib/coffeebrew_jekyll_archives/generator.rb` | This is the generator that reads the configuration and generate the index pages. |
|
463
|
+
| `lib/coffeebrew_jekyll_archives/page.rb` | This is the abstract model of the index pages. |
|
464
|
+
| `lib/coffeebrew_jekyll_archives/validator.rb` | This validates the configuration. |
|
465
|
+
| `lib/coffeebrew_jekyll_archives/version.rb` | This contains the version number of the gem. |
|
466
|
+
| `lib/coffeebrew_jekyll_archives.rb` | This is the entry point of the gem, and it loads the dependencies. |
|
467
|
+
|
468
|
+
### Test cases directory structure
|
469
|
+
|
470
|
+
All the test cases and fixtures live in the `/spec` directory:
|
471
|
+
|
472
|
+
Note: Some files have been omitted for clarity.
|
473
|
+
|
474
|
+
```bash
|
475
|
+
spec
|
476
|
+
├── coffeebrew_jekyll_archives_spec.rb
|
477
|
+
├── dest
|
478
|
+
├── fixtures
|
479
|
+
│ ├── _config.yml
|
480
|
+
│ ├── _data
|
481
|
+
│ │ └── navigation.yml
|
482
|
+
│ ├── _includes
|
483
|
+
│ │ └── navigation.html
|
484
|
+
│ ├── _layouts
|
485
|
+
│ │ ├── archive.html
|
486
|
+
│ │ └── default.html
|
487
|
+
│ └── _posts
|
488
|
+
│ ├── 2021-03-12-test-post-1.md
|
489
|
+
│ ├── 2021-03-28-test-post-2.md
|
490
|
+
│ ├── 2021-05-03-test-post-3.md
|
491
|
+
│ ├── 2021-05-03-test-post-4.md
|
492
|
+
│ ├── 2022-01-27-test-post-5.md
|
493
|
+
│ ├── 2022-03-12-test-post-6.md
|
494
|
+
│ ├── 2022-11-23-test-post-7.md
|
495
|
+
│ └── 2023-02-21-test-post-8.md
|
496
|
+
├── scenarios
|
497
|
+
│ ├── default
|
498
|
+
│ │ ├── _site
|
499
|
+
│ │ │ ├── archives
|
500
|
+
│ │ │ │ ├── 2021
|
501
|
+
│ │ │ │ │ ├── 03
|
502
|
+
│ │ │ │ │ │ ├── 12
|
503
|
+
│ │ │ │ │ │ │ └── index.html
|
504
|
+
│ │ │ │ │ │ ├── 28
|
505
|
+
│ │ │ │ │ │ │ └── index.html
|
506
|
+
│ │ │ │ │ │ └── index.html
|
507
|
+
│ │ │ │ │ ├── 05
|
508
|
+
│ │ │ │ │ │ ├── 03
|
509
|
+
│ │ │ │ │ │ │ └── index.html
|
510
|
+
│ │ │ │ │ │ └── index.html
|
511
|
+
│ │ │ │ │ └── index.html
|
512
|
+
│ │ │ │ └── 2023
|
513
|
+
│ │ │ │ ├── 02
|
514
|
+
│ │ │ │ │ ├── 21
|
515
|
+
│ │ │ │ │ │ └── index.html
|
516
|
+
│ │ │ │ │ └── index.html
|
517
|
+
│ │ │ │ └── index.html
|
518
|
+
│ │ │ └── archives.html
|
519
|
+
│ │ └── context.rb
|
520
|
+
│ └── invalid_config_keys
|
521
|
+
│ └── context.rb
|
522
|
+
└── spec_helper.rb
|
523
|
+
```
|
524
|
+
|
525
|
+
The files that are currently in the repo:
|
526
|
+
|
527
|
+
| File | Description |
|
528
|
+
| --- | --- |
|
529
|
+
| `spec/coffeebrew_jekyll_archives_spec.rb` | This is the main RSpec file to be executed. It contains all the contexts of various scenarios. |
|
530
|
+
| `spec/dest/` | This directory is where generated files are located. It will be deleted immediately after each context is executed. |
|
531
|
+
| `spec/fixtures/` | This directory follows the Jekyll site source structure and contains the minimal files required to generate the archive index pages. |
|
532
|
+
| `spec/fixtures/_posts` | This directory contains the test posts, you can add more to it to test your new feature. |
|
533
|
+
| `spec/scenarios/` | This directory contains the expected files of various test scenarios. |
|
534
|
+
| `spec/scenarios/<scenario>/` | This is the scenario name. |
|
535
|
+
| `spec/scenarios/<scenario>/_site/` | This directory contains the expected archive index pages. |
|
536
|
+
| `spec/scenarios/<scenario>/context.rb` | This is the file that sets up the context for the test case. |
|
537
|
+
| `spec/spec_helper.rb` | This contains RSpec configuration and certain convenience methods for the main RSpec file. |
|
538
|
+
|
539
|
+
### Writing test cases
|
540
|
+
|
541
|
+
There is a certain convention to follow when writing new test scenarios. The recommendation is to use the rake tasks
|
542
|
+
provided in the gem to generate the scenario files.
|
543
|
+
|
544
|
+
For success scenarios, run:
|
545
|
+
|
546
|
+
```bash
|
547
|
+
bundle exec rake coffeebrew:jekyll:archives:test:create_success[test_scenario]
|
548
|
+
```
|
549
|
+
|
550
|
+
This will generate a placeholder file and directory:
|
551
|
+
|
552
|
+
```bash
|
553
|
+
spec
|
554
|
+
├── coffeebrew_jekyll_archives_spec.rb
|
555
|
+
├── scenarios
|
556
|
+
│ └── test_scenario
|
557
|
+
│ ├── _site
|
558
|
+
│ └── context.rb
|
559
|
+
└── spec_helper.rb
|
560
|
+
```
|
561
|
+
|
562
|
+
Where the `context.rb` file will be pre-populated:
|
563
|
+
|
564
|
+
```ruby
|
565
|
+
# frozen_string_literal: true
|
566
|
+
|
567
|
+
CONTEXT_TEST_SCENARIO = "when using test_scenario config"
|
568
|
+
|
569
|
+
RSpec.shared_context CONTEXT_TEST_SCENARIO do
|
570
|
+
let(:scenario) { "test_scenario" }
|
571
|
+
let(:overrides) {} # TODO: remove if unused
|
572
|
+
let(:generated_files) {} # TODO: remove if unused
|
573
|
+
let(:expected_files) do
|
574
|
+
[
|
575
|
+
]
|
576
|
+
end
|
577
|
+
end
|
578
|
+
```
|
579
|
+
|
580
|
+
For failure scenarios, run:
|
581
|
+
|
582
|
+
```bash
|
583
|
+
bundle exec rake coffeebrew:jekyll:archives:test:create_failure[test_scenario]
|
584
|
+
```
|
585
|
+
|
586
|
+
This will generate a placeholder file and directory:
|
587
|
+
|
588
|
+
```bash
|
589
|
+
spec
|
590
|
+
├── coffeebrew_jekyll_archives_spec.rb
|
591
|
+
├── scenarios
|
592
|
+
│ └── test_scenario
|
593
|
+
│ └── context.rb
|
594
|
+
└── spec_helper.rb
|
595
|
+
```
|
596
|
+
|
597
|
+
Where the `context.rb` file will be pre-populated:
|
598
|
+
|
599
|
+
```ruby
|
600
|
+
# frozen_string_literal: true
|
601
|
+
|
602
|
+
CONTEXT_TEST_SCENARIO = "when using test_scenario config"
|
603
|
+
|
604
|
+
RSpec.shared_context CONTEXT_TEST_SCENARIO do
|
605
|
+
let(:scenario) { "test_scenario" }
|
606
|
+
let(:generated_files) { [] }
|
607
|
+
let(:expected_files) { [] }
|
608
|
+
let(:overrides) do
|
609
|
+
{
|
610
|
+
}
|
611
|
+
end
|
612
|
+
|
613
|
+
let(:expected_errors) do
|
614
|
+
[
|
615
|
+
]
|
616
|
+
end
|
617
|
+
end
|
618
|
+
```
|
619
|
+
|
620
|
+
If you do write other test cases that are not asserting the generated files like above, you can initiate your
|
621
|
+
convention. The repo owner will evaluate the PR and accept the convention if it fits the repo existing convention, or
|
622
|
+
will recommend an alternative if it doesn't.
|
623
|
+
|
624
|
+
## License
|
625
|
+
|
626
|
+
See the [LICENSE](LICENSE) file.
|
@@ -0,0 +1,30 @@
|
|
1
|
+
---
|
2
|
+
archives:
|
3
|
+
navigation:
|
4
|
+
data: "navigation"
|
5
|
+
name: "Archives"
|
6
|
+
before:
|
7
|
+
after:
|
8
|
+
depths: 3
|
9
|
+
title_format:
|
10
|
+
root:
|
11
|
+
type: "string"
|
12
|
+
style: "/"
|
13
|
+
year:
|
14
|
+
type: "date"
|
15
|
+
style: "%Y"
|
16
|
+
month:
|
17
|
+
type: "date"
|
18
|
+
style: "%b, %Y"
|
19
|
+
day:
|
20
|
+
type: "date"
|
21
|
+
style: "%d %b, %Y"
|
22
|
+
root_dir: "/"
|
23
|
+
root_basename: "archives"
|
24
|
+
index_root: "/archives"
|
25
|
+
index_basename: "index"
|
26
|
+
permalink:
|
27
|
+
root: "/:root_dir"
|
28
|
+
year: "/:root_dir/:index_root/:year"
|
29
|
+
month: "/:root_dir/:index_root/:year/:month"
|
30
|
+
day: "/:root_dir/:index_root/:year/:month/:day"
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "./page"
|
4
|
+
require_relative "./validator"
|
5
|
+
|
6
|
+
module Coffeebrew
|
7
|
+
module Jekyll
|
8
|
+
module Archives
|
9
|
+
class Generator < ::Jekyll::Generator
|
10
|
+
safe true
|
11
|
+
priority :lowest
|
12
|
+
|
13
|
+
def generate(site)
|
14
|
+
@site = site
|
15
|
+
|
16
|
+
validate!
|
17
|
+
|
18
|
+
@site.pages << root_page
|
19
|
+
@site.data["archives"] = root_page
|
20
|
+
|
21
|
+
return unless navigation_config
|
22
|
+
|
23
|
+
generate_navigation
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def config
|
29
|
+
@config ||= ::Jekyll::Utils.deep_merge_hashes(default_config["archives"], @site.config["archives"].to_h)
|
30
|
+
end
|
31
|
+
|
32
|
+
def validate!
|
33
|
+
validator = Coffeebrew::Jekyll::Archives::Validator.new(config)
|
34
|
+
validator.validate!
|
35
|
+
end
|
36
|
+
|
37
|
+
def root_page
|
38
|
+
@root_page ||= Coffeebrew::Jekyll::Archives::Page.new(
|
39
|
+
:root, @site, config, nil, @site.posts.docs, config["depths"],
|
40
|
+
year: 1, month: 1, day: 1
|
41
|
+
)
|
42
|
+
end
|
43
|
+
|
44
|
+
def navigation_config
|
45
|
+
@navigation_config ||= config["navigation"]
|
46
|
+
end
|
47
|
+
|
48
|
+
def navigation_data
|
49
|
+
@navigation_data ||= @site.data[navigation_config["data"]]
|
50
|
+
end
|
51
|
+
|
52
|
+
def default_config_path
|
53
|
+
@default_config_path ||= File.expand_path("config.yml", __dir__)
|
54
|
+
end
|
55
|
+
|
56
|
+
def default_config
|
57
|
+
@default_config ||= YAML.safe_load(File.read(default_config_path))
|
58
|
+
end
|
59
|
+
|
60
|
+
def menu_data
|
61
|
+
@menu_data ||= {
|
62
|
+
"name" => navigation_config["name"],
|
63
|
+
"link" => root_page.url
|
64
|
+
}
|
65
|
+
end
|
66
|
+
|
67
|
+
def find_menu_index(menu_name)
|
68
|
+
navigation_data.index do |menu|
|
69
|
+
menu["name"] == menu_name
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def insert_position
|
74
|
+
@insert_position ||= if navigation_config["before"]
|
75
|
+
[navigation_config["before"], 0]
|
76
|
+
elsif navigation_config["after"]
|
77
|
+
[navigation_config["after"], 1]
|
78
|
+
else
|
79
|
+
[]
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def generate_navigation
|
84
|
+
if insert_position.empty?
|
85
|
+
navigation_data << menu_data
|
86
|
+
else
|
87
|
+
menu_name, offset = insert_position
|
88
|
+
found_index = find_menu_index(menu_name)
|
89
|
+
navigation_data.insert(found_index + offset, menu_data)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,181 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Coffeebrew
|
4
|
+
module Jekyll
|
5
|
+
module Archives
|
6
|
+
class Page < ::Jekyll::Page # rubocop:disable Metrics/ClassLength
|
7
|
+
HIERARCHY = {
|
8
|
+
"root" => "year",
|
9
|
+
"year" => "month",
|
10
|
+
"month" => "day"
|
11
|
+
}.freeze
|
12
|
+
|
13
|
+
DEPTHS = {
|
14
|
+
"root" => 0,
|
15
|
+
"year" => 1,
|
16
|
+
"month" => 2,
|
17
|
+
"day" => 3
|
18
|
+
}.freeze
|
19
|
+
|
20
|
+
attr_reader :type, :date, :parent, :collection
|
21
|
+
|
22
|
+
def initialize(type, site, config, parent, collection, depths, year:, month:, day:) # rubocop:disable Lint/MissingSuper, Metrics/ParameterLists
|
23
|
+
@type = type
|
24
|
+
@site = site
|
25
|
+
@config = config
|
26
|
+
@base = site.source
|
27
|
+
@date = Date.new(year.to_i, month.to_i, day.to_i)
|
28
|
+
@ext = ".html"
|
29
|
+
@parent = parent
|
30
|
+
@collection = collection
|
31
|
+
@depths = depths
|
32
|
+
build_data
|
33
|
+
end
|
34
|
+
|
35
|
+
def sub_pages
|
36
|
+
@sub_pages ||= if current_depth < @depths
|
37
|
+
child_type = HIERARCHY[type.to_s].to_sym
|
38
|
+
group_collection_by(collection, child_type).each_with_object([]) do |(attr, items), pages|
|
39
|
+
fields = date_fields.merge(child_type => attr)
|
40
|
+
child_page = Page.new(child_type, @site, @config, self, items, @depths, **fields)
|
41
|
+
add_child_page(pages, child_page)
|
42
|
+
end
|
43
|
+
else
|
44
|
+
[]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def url_placeholders
|
49
|
+
{
|
50
|
+
path: dir,
|
51
|
+
basename: basename,
|
52
|
+
output_ext: output_ext
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
def ancestors
|
57
|
+
@ancestors ||= begin
|
58
|
+
arr = []
|
59
|
+
current_parent = parent
|
60
|
+
while current_parent
|
61
|
+
arr.unshift(current_parent)
|
62
|
+
current_parent = current_parent.parent
|
63
|
+
end
|
64
|
+
arr
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def dir
|
69
|
+
@dir ||= begin
|
70
|
+
format = @config.dig("permalink", type.to_s)
|
71
|
+
::Jekyll::URL.new(
|
72
|
+
template: format,
|
73
|
+
placeholders: dir_placeholders,
|
74
|
+
permalink: nil
|
75
|
+
).to_s
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def year
|
80
|
+
@year ||= date.strftime("%Y")
|
81
|
+
end
|
82
|
+
|
83
|
+
def month
|
84
|
+
@month ||= date.strftime("%m")
|
85
|
+
end
|
86
|
+
|
87
|
+
def day
|
88
|
+
@day ||= date.strftime("%d")
|
89
|
+
end
|
90
|
+
|
91
|
+
def title
|
92
|
+
@title ||= case title_format_type
|
93
|
+
when :date
|
94
|
+
date.strftime(title_format_style)
|
95
|
+
when :string
|
96
|
+
format(title_format_style, year: year, month: month, day: day)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def basename
|
101
|
+
@basename ||= case type.to_sym
|
102
|
+
when :root
|
103
|
+
@config["root_basename"]
|
104
|
+
else
|
105
|
+
@config["index_basename"]
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def name
|
110
|
+
@name ||= "#{basename}#{ext}"
|
111
|
+
end
|
112
|
+
|
113
|
+
private
|
114
|
+
|
115
|
+
def date_fields
|
116
|
+
@date_fields ||= { year: year, month: month, day: day }
|
117
|
+
end
|
118
|
+
|
119
|
+
def add_child_page(pages, child_page)
|
120
|
+
pages << child_page
|
121
|
+
@site.pages << child_page
|
122
|
+
end
|
123
|
+
|
124
|
+
def dir_placeholders
|
125
|
+
@dir_placeholders ||= {
|
126
|
+
root_dir: @config["root_dir"],
|
127
|
+
index_root: @config["index_root"],
|
128
|
+
year: year,
|
129
|
+
month: month,
|
130
|
+
day: day
|
131
|
+
}
|
132
|
+
end
|
133
|
+
|
134
|
+
def current_depth
|
135
|
+
@current_depth ||= DEPTHS[type.to_s]
|
136
|
+
end
|
137
|
+
|
138
|
+
def title_format
|
139
|
+
@title_format ||= @config.dig("title_format", type.to_s)
|
140
|
+
end
|
141
|
+
|
142
|
+
def title_format_type
|
143
|
+
@title_format_type ||= title_format["type"].to_sym
|
144
|
+
end
|
145
|
+
|
146
|
+
def title_format_style
|
147
|
+
@title_format_style ||= title_format["style"]
|
148
|
+
end
|
149
|
+
|
150
|
+
def root_index_path
|
151
|
+
@root_index_path ||= "#{@config['root_dir']}#{@config['root_basename']}.html"
|
152
|
+
end
|
153
|
+
|
154
|
+
def build_data # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
155
|
+
@data = {
|
156
|
+
"dir" => dir,
|
157
|
+
"sub_pages" => sub_pages,
|
158
|
+
"root" => root_index_path,
|
159
|
+
"ancestors" => ancestors,
|
160
|
+
"parent" => parent,
|
161
|
+
"collection" => collection,
|
162
|
+
"title" => title,
|
163
|
+
"year" => year,
|
164
|
+
"month" => month,
|
165
|
+
"day" => day
|
166
|
+
}
|
167
|
+
|
168
|
+
data.default_proc = proc do |_, key|
|
169
|
+
site.frontmatter_defaults.find(relative_path, :archives, key)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def group_collection_by(collection, attr)
|
174
|
+
collection.group_by do |item|
|
175
|
+
item.date.send(attr)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Coffeebrew
|
4
|
+
module Jekyll
|
5
|
+
module Archives
|
6
|
+
class Validator
|
7
|
+
ALLOWED_CONFIG_KEYS = {
|
8
|
+
"navigation" => {
|
9
|
+
"data" => [],
|
10
|
+
"name" => [],
|
11
|
+
"before" => [],
|
12
|
+
"after" => []
|
13
|
+
},
|
14
|
+
"depths" => [1, 2, 3],
|
15
|
+
"title_format" => {
|
16
|
+
"root" => {
|
17
|
+
"type" => %w[string date],
|
18
|
+
"style" => []
|
19
|
+
},
|
20
|
+
"year" => {
|
21
|
+
"type" => %w[string date],
|
22
|
+
"style" => []
|
23
|
+
},
|
24
|
+
"month" => {
|
25
|
+
"type" => %w[string date],
|
26
|
+
"style" => []
|
27
|
+
},
|
28
|
+
"day" => {
|
29
|
+
"type" => %w[string date],
|
30
|
+
"style" => []
|
31
|
+
}
|
32
|
+
},
|
33
|
+
"root_dir" => [],
|
34
|
+
"root_basename" => [],
|
35
|
+
"index_root" => [],
|
36
|
+
"index_basename" => [],
|
37
|
+
"permalink" => {
|
38
|
+
"root" => [],
|
39
|
+
"year" => [],
|
40
|
+
"month" => [],
|
41
|
+
"day" => []
|
42
|
+
}
|
43
|
+
}.freeze
|
44
|
+
|
45
|
+
def initialize(config)
|
46
|
+
@config = config
|
47
|
+
@errors = []
|
48
|
+
end
|
49
|
+
|
50
|
+
def validate!
|
51
|
+
parse(@config, ALLOWED_CONFIG_KEYS, ["archives"])
|
52
|
+
|
53
|
+
return if @errors.empty?
|
54
|
+
|
55
|
+
::Jekyll.logger.error "'archives' config is set incorrectly."
|
56
|
+
::Jekyll.logger.error "Errors:", @errors
|
57
|
+
|
58
|
+
raise ::Jekyll::Errors::InvalidConfigurationError, "'archives' config is set incorrectly."
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def parse(hash, allowed_keys, parent_key)
|
64
|
+
hash.each do |key, configured_value|
|
65
|
+
allowed_values = allowed_keys[key]
|
66
|
+
new_parent_key = parent_key + [key]
|
67
|
+
|
68
|
+
next if configured_in_allowed_values?(allowed_values, configured_value)
|
69
|
+
|
70
|
+
if same_hash_type?(allowed_values, configured_value)
|
71
|
+
next parse(configured_value, allowed_values, new_parent_key)
|
72
|
+
end
|
73
|
+
|
74
|
+
add_error(new_parent_key, allowed_values, configured_value)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def same_hash_type?(allowed_values, configured_value)
|
79
|
+
allowed_values.is_a?(Hash) && configured_value.is_a?(Hash)
|
80
|
+
end
|
81
|
+
|
82
|
+
def primitive?(value)
|
83
|
+
value.nil? || value.is_a?(String) || value.is_a?(Numeric)
|
84
|
+
end
|
85
|
+
|
86
|
+
def configured_in_allowed_values?(allowed_values, configured_value)
|
87
|
+
allowed_values.is_a?(Array) && primitive?(configured_value) &&
|
88
|
+
(allowed_values.empty? || allowed_values.include?(configured_value))
|
89
|
+
end
|
90
|
+
|
91
|
+
def add_error(parent_key, allowed_values, configured_value)
|
92
|
+
@errors << { key: parent_key.join("."), expected: allowed_values, got: configured_value }
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
metadata
ADDED
@@ -0,0 +1,175 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: coffeebrew_jekyll_archives
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Coffee Brew Apps
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-04-06 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: '4.0'
|
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: '4.0'
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '5.0'
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: pry
|
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: bundler
|
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: 13.0.6
|
68
|
+
type: :development
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: 13.0.6
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: rspec
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: 3.12.0
|
82
|
+
type: :development
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - "~>"
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: 3.12.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.13.0
|
96
|
+
type: :development
|
97
|
+
prerelease: false
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - "~>"
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: 0.13.0
|
103
|
+
- !ruby/object:Gem::Dependency
|
104
|
+
name: rubocop-rake
|
105
|
+
requirement: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - "~>"
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 0.6.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.6.0
|
117
|
+
- !ruby/object:Gem::Dependency
|
118
|
+
name: rubocop-rspec
|
119
|
+
requirement: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - "~>"
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: 2.19.0
|
124
|
+
type: :development
|
125
|
+
prerelease: false
|
126
|
+
version_requirements: !ruby/object:Gem::Requirement
|
127
|
+
requirements:
|
128
|
+
- - "~>"
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: 2.19.0
|
131
|
+
description: A Jekyll plugin to generate blog post archives
|
132
|
+
email:
|
133
|
+
- coffeebrewapps@gmail.com
|
134
|
+
executables: []
|
135
|
+
extensions: []
|
136
|
+
extra_rdoc_files:
|
137
|
+
- README.md
|
138
|
+
- CHANGELOG.md
|
139
|
+
- LICENSE
|
140
|
+
files:
|
141
|
+
- CHANGELOG.md
|
142
|
+
- LICENSE
|
143
|
+
- README.md
|
144
|
+
- lib/coffeebrew_jekyll_archives.rb
|
145
|
+
- lib/coffeebrew_jekyll_archives/config.yml
|
146
|
+
- lib/coffeebrew_jekyll_archives/generator.rb
|
147
|
+
- lib/coffeebrew_jekyll_archives/page.rb
|
148
|
+
- lib/coffeebrew_jekyll_archives/validator.rb
|
149
|
+
- lib/coffeebrew_jekyll_archives/version.rb
|
150
|
+
homepage: https://coffeebrewapps.com/coffeebrew_jekyll_archives
|
151
|
+
licenses:
|
152
|
+
- MIT
|
153
|
+
metadata:
|
154
|
+
allowed_push_host: https://rubygems.org
|
155
|
+
post_install_message:
|
156
|
+
rdoc_options: []
|
157
|
+
require_paths:
|
158
|
+
- lib/coffeebrew_jekyll_archives
|
159
|
+
- lib
|
160
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
161
|
+
requirements:
|
162
|
+
- - ">="
|
163
|
+
- !ruby/object:Gem::Version
|
164
|
+
version: 2.7.0
|
165
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
166
|
+
requirements:
|
167
|
+
- - ">="
|
168
|
+
- !ruby/object:Gem::Version
|
169
|
+
version: '0'
|
170
|
+
requirements: []
|
171
|
+
rubygems_version: 3.4.6
|
172
|
+
signing_key:
|
173
|
+
specification_version: 4
|
174
|
+
summary: A Jekyll plugin to generate blog post archives
|
175
|
+
test_files: []
|