jekyll-podcast 0.9.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: 69e80669ca56561da9578401d9afbd342b681eb5648dfcca7b395a03b502579a
4
+ data.tar.gz: f0884813435aa6d532fe45bf99b889c82fcf13d8601ab3b579eb12161448e134
5
+ SHA512:
6
+ metadata.gz: 78c530532b4b91b0fc0e17c7ce31f170a51a9582cf07e638ef25d7239cb674b8ccdeb45e0cc72581b5a491a63f7afcf1813a7406325a9a8cc6ebacaf822b3441
7
+ data.tar.gz: 1f7dfaa39fc4fa7a0e1e20db83061c3d811a8272a24338f0f55eca4c3199f1d7051ecc5f5935463457bd1897031a3ae2577f39b7f3c2b8de8d5c34e3d58529f6
data/.gitignore ADDED
@@ -0,0 +1,15 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ /.vscode/
10
+ /spec/dest/
11
+ .jekyll-cache
12
+ .nova
13
+
14
+ # rspec failure tracking
15
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,8 @@
1
+ require: rubocop-rspec
2
+
3
+ AllCops:
4
+ TargetRubyVersion: 3.0
5
+ NewCops: enable
6
+
7
+ Layout/LineLength:
8
+ Max: 120
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.1.0] - 2021-09-28
4
+
5
+ - Initial release
data/Gemfile ADDED
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ # Specify your gem's dependencies in jekyll-podcast.gemspec
6
+ gemspec
7
+
8
+ gem 'rake', '~> 13.0'
9
+
10
+ gem 'rspec', '~> 3.0'
11
+
12
+ gem 'rubocop', '~> 1.7'
13
+ gem 'rubocop-rspec', '~> 2.12'
14
+
15
+ gem 'jekyll', '~> 4.2'
16
+
17
+ gem 'nokogiri', '~> 1.13'
18
+
19
+ gem 'rubocop-rake', '~> 0.6.0'
data/Gemfile.lock ADDED
@@ -0,0 +1,130 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ jekyll-podcast (0.9.0)
5
+ jekyll (~> 4.2)
6
+ json-schema (~> 2.6)
7
+ mp3info (~> 0.8.5)
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ addressable (2.8.0)
13
+ public_suffix (>= 2.0.2, < 5.0)
14
+ ast (2.4.2)
15
+ colorator (1.1.0)
16
+ concurrent-ruby (1.1.10)
17
+ diff-lcs (1.5.0)
18
+ em-websocket (0.5.3)
19
+ eventmachine (>= 0.12.9)
20
+ http_parser.rb (~> 0)
21
+ eventmachine (1.2.7)
22
+ ffi (1.15.5)
23
+ forwardable-extended (2.6.0)
24
+ http_parser.rb (0.8.0)
25
+ i18n (1.12.0)
26
+ concurrent-ruby (~> 1.0)
27
+ jekyll (4.2.2)
28
+ addressable (~> 2.4)
29
+ colorator (~> 1.0)
30
+ em-websocket (~> 0.5)
31
+ i18n (~> 1.0)
32
+ jekyll-sass-converter (~> 2.0)
33
+ jekyll-watch (~> 2.0)
34
+ kramdown (~> 2.3)
35
+ kramdown-parser-gfm (~> 1.0)
36
+ liquid (~> 4.0)
37
+ mercenary (~> 0.4.0)
38
+ pathutil (~> 0.9)
39
+ rouge (~> 3.0)
40
+ safe_yaml (~> 1.0)
41
+ terminal-table (~> 2.0)
42
+ jekyll-sass-converter (2.2.0)
43
+ sassc (> 2.0.1, < 3.0)
44
+ jekyll-watch (2.2.1)
45
+ listen (~> 3.0)
46
+ json (2.6.2)
47
+ json-schema (2.8.1)
48
+ addressable (>= 2.4)
49
+ kramdown (2.4.0)
50
+ rexml
51
+ kramdown-parser-gfm (1.1.0)
52
+ kramdown (~> 2.0)
53
+ liquid (4.0.3)
54
+ listen (3.7.1)
55
+ rb-fsevent (~> 0.10, >= 0.10.3)
56
+ rb-inotify (~> 0.9, >= 0.9.10)
57
+ mercenary (0.4.0)
58
+ mp3info (0.8.5)
59
+ ruby-mp3info (>= 0.8.5)
60
+ nokogiri (1.13.8-arm64-darwin)
61
+ racc (~> 1.4)
62
+ parallel (1.22.1)
63
+ parser (3.1.2.0)
64
+ ast (~> 2.4.1)
65
+ pathutil (0.16.2)
66
+ forwardable-extended (~> 2.6)
67
+ public_suffix (4.0.7)
68
+ racc (1.6.0)
69
+ rainbow (3.1.1)
70
+ rake (13.0.6)
71
+ rb-fsevent (0.11.1)
72
+ rb-inotify (0.10.1)
73
+ ffi (~> 1.0)
74
+ regexp_parser (2.5.0)
75
+ rexml (3.2.5)
76
+ rouge (3.30.0)
77
+ rspec (3.11.0)
78
+ rspec-core (~> 3.11.0)
79
+ rspec-expectations (~> 3.11.0)
80
+ rspec-mocks (~> 3.11.0)
81
+ rspec-core (3.11.0)
82
+ rspec-support (~> 3.11.0)
83
+ rspec-expectations (3.11.0)
84
+ diff-lcs (>= 1.2.0, < 2.0)
85
+ rspec-support (~> 3.11.0)
86
+ rspec-mocks (3.11.1)
87
+ diff-lcs (>= 1.2.0, < 2.0)
88
+ rspec-support (~> 3.11.0)
89
+ rspec-support (3.11.0)
90
+ rubocop (1.32.0)
91
+ json (~> 2.3)
92
+ parallel (~> 1.10)
93
+ parser (>= 3.1.0.0)
94
+ rainbow (>= 2.2.2, < 4.0)
95
+ regexp_parser (>= 1.8, < 3.0)
96
+ rexml (>= 3.2.5, < 4.0)
97
+ rubocop-ast (>= 1.19.1, < 2.0)
98
+ ruby-progressbar (~> 1.7)
99
+ unicode-display_width (>= 1.4.0, < 3.0)
100
+ rubocop-ast (1.19.1)
101
+ parser (>= 3.1.1.0)
102
+ rubocop-rake (0.6.0)
103
+ rubocop (~> 1.0)
104
+ rubocop-rspec (2.12.1)
105
+ rubocop (~> 1.31)
106
+ ruby-mp3info (0.8.10)
107
+ ruby-progressbar (1.11.0)
108
+ safe_yaml (1.0.5)
109
+ sassc (2.4.0)
110
+ ffi (~> 1.9)
111
+ terminal-table (2.0.0)
112
+ unicode-display_width (~> 1.1, >= 1.1.1)
113
+ unicode-display_width (1.8.0)
114
+
115
+ PLATFORMS
116
+ arm64-darwin-20
117
+ arm64-darwin-21
118
+
119
+ DEPENDENCIES
120
+ jekyll (~> 4.2)
121
+ jekyll-podcast!
122
+ nokogiri (~> 1.13)
123
+ rake (~> 13.0)
124
+ rspec (~> 3.0)
125
+ rubocop (~> 1.7)
126
+ rubocop-rake (~> 0.6.0)
127
+ rubocop-rspec (~> 2.12)
128
+
129
+ BUNDLED WITH
130
+ 2.3.9
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2021 Nathan Bottomley
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
13
+ all 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
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,335 @@
1
+ # Jekyll::Podcast
2
+
3
+ `jekyll-podcast` converts a Jekyll blog into a podcast webpage. It provides you with all the functionality you need to make your podcast fully accessible from your webpage, and it creates a podcast feed which you can submit to Apple Podcasts, Google Podcasts, Spotify or any other podcast directory.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'jekyll-podcast'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ ```shell
16
+ bundle install
17
+ ```
18
+
19
+ Or install it yourself as:
20
+
21
+ ```shell
22
+ gem install jekyll-podcast
23
+ ```
24
+
25
+ ## Usage
26
+
27
+ ### Providing information about your podcast
28
+
29
+ Most of the important information about your podcast — the title, the owner, the category, the subcategory and so on should appear in a `podcast` block in `_config.yml`.
30
+
31
+ ```yaml
32
+ # _config.yml
33
+
34
+ podcast:
35
+ title: "Flight Through Entirety: A Doctor Who Podcast"
36
+ subtitle: &subtitle >-
37
+ Flying through the entirety of Doctor Who. Originally with cake,but now with guests.
38
+ # I've made the description and the summary
39
+ # the same as the subtitle, but you can do
40
+ # whatever you like here.
41
+ description: *subtitle
42
+ summary: *subtitle
43
+ email: flightthroughentirety@gmail.com
44
+ language: en-AU
45
+ author: Flight Through Entirety
46
+ owner: Nathan Bottomley
47
+ explicit: false
48
+ category: TV &amp; Film
49
+ subcategory: TV Reviews
50
+ complete: no
51
+ ```
52
+
53
+ >Explanations of all of the fields here can be found on [Apple's page about podcast feed tags](https://help.apple.com/itc/podcasts_connect/#/itcb54353390). A list of podcast categories and subcategories [can be found here](https://podcasters.apple.com/support/1691-apple-podcasts-categories).
54
+
55
+ You will also need to provide your podcast artwork, which should be a JPEG file 3000 × 3000 pixels in size. `jekyll-podcast` will expect to find this file at `/assets/images/podcast-logo.jpeg`.
56
+
57
+ ### Providing information about your podcast episodes
58
+
59
+ Each post in the `_posts` directory will correspond to an episode of your podcast. So, for example, the publication date of the post will be the publication date of the episode, and the content of the post will be the episode's description or shownotes, which will (normally) be displayed in your listeners' podcast player.
60
+
61
+ Other information about your podcast episodes should be provided in each post's front matter. Here's an example.
62
+
63
+ ```yaml
64
+ tags: #optional
65
+ - Series 6
66
+ - The Eleventh Doctor
67
+ contributors: #also optional
68
+ - Nathan Bottomley
69
+ podcast:
70
+ # the episode number
71
+ episode: 217
72
+ # the episode filename, including the extension
73
+ file: >-
74
+ FTE 217, Gaslight Girlboss Ginger (Day of the Moon).mp3
75
+ # optional
76
+ recording_date: 2021-08-01
77
+ ```
78
+
79
+ ### The episode files
80
+
81
+ By default, you will store your episodes in `/assets/episodes`, and they will be served directly from your website.
82
+
83
+ If you use an analytics service that requires a URL prefix to track your episodes' data, you will need to provide that prefix as part of the `podcast` block in `_config.yml`.
84
+
85
+ ```yaml
86
+ # _config.yml
87
+
88
+ podcast:
89
+ tracking_prefix: https://dts.podtrac.com/redirect.mp3
90
+ ```
91
+
92
+ If you use a CDN or an S3-compatible storage solution to host your podcast episodes, you will need to provide the URL for that sevice. You must also store your episodes in a folder called `/_episodes`, so that Jekyll doesn't include the episode files in the website it builds.
93
+
94
+ ```yaml
95
+ # _config.yml
96
+
97
+ podcast:
98
+ remote_episode_host: https://flight-through-entirety.us-east-1.linodeobjects.com
99
+ ```
100
+
101
+ > If you store your episodes on some other service, you will have to take care of uploading the episodes to that service yourself. I generally write a build script using `rsync` or `s3cmd sync` to do this.
102
+
103
+ ### Creating your podcast feed
104
+
105
+ If you set up your `_config.yml` file and the front matter of your posts as specified above, `jekyll-podcast` will have enough information to create your podcast feed.
106
+
107
+ Your podcast feed will appear in your `_site` directory at `feed/podcast`.
108
+
109
+ ### Your shownotes
110
+
111
+ The contents of each episode's post will appear on the website, as usual, but it will also be used as the description or shownotes for your episode and displayed in your listeners' podcast players.
112
+
113
+ It's easy to make a podcast player show a different description from the post displayed on your site. Just create an include called `post-feed-content.html` in the `_includes` folder and use it to define the content that you want to appear in a podcast player. Here's an example.
114
+
115
+ ```html
116
+ <!-- post-feed-content.html -->
117
+
118
+ <p>
119
+ <em>
120
+ {{ post.star_trek.series }},
121
+ {{ post.star_trek.episode }}.
122
+ First broadcast on {{ post.star_trek.broadcast | date: "%A, %e %B %Y" }}
123
+ </em>
124
+ </p>
125
+
126
+ {{ post.content }}
127
+ ```
128
+
129
+ ### Podcast episode permalinks
130
+
131
+ Unlike a blog, a podcast website should have simple permalinks. Best practice tends to be just the episode number.
132
+
133
+ ```url
134
+ https://flightthroughentirety.com/217
135
+ ```
136
+
137
+ To make this possible, `jekyll-podcast` provides a `:podcast_episode` placeholder, which you can use in your default permalink definitions in `_config.yml`.
138
+
139
+ ```yaml
140
+ # _config.yml
141
+
142
+ - scope:
143
+ path: ""
144
+ type: posts
145
+ values:
146
+ permalink: /:podcast_episode/
147
+ ```
148
+
149
+ > You can combine this placeholder with other placeholders if you like. One possibility might be combining the episode number with the slug, like this:
150
+ >
151
+ > ```yaml
152
+ > # _config.yml
153
+ >
154
+ > values:
155
+ > permalink: /:podcast_episode-:slug/
156
+ > ```
157
+ >
158
+ >
159
+ > Remember to put the `/` at the end of the permalink pattern, so that you don't end up with the `.html` suffix at the end of your URLs.
160
+
161
+ ### Podcast episode data
162
+
163
+ When `jekyll-podcast` builds your site, it analyses the podcast episodes in your `assets/episodes` folder (or your `_episodes` folder). As a result, the following information becomes available to your Liquid templates.
164
+
165
+ ```liquid
166
+ {{ post.podcast.duration }}
167
+ → 0:57:22
168
+
169
+ {{ post.podcast.size_in_megabytes }}
170
+ → 40.1 MB
171
+ ```
172
+
173
+ You might want to consider adding the recording date to the podcast blog in the front matter of your posts, so that you can display it in your posts as well.
174
+
175
+ ```yaml
176
+ podcast:
177
+ recording_date: 2022-07-13
178
+ ```
179
+
180
+ ```liquid
181
+ {{ post.podcast.recording_date | date: "%A, %e %B %Y" }}
182
+ → Wednesday, 13 July 2022
183
+ ```
184
+
185
+ ### Including an `<audio>` tag
186
+
187
+ You should also create an include for your post so that your listeners can listen to the episodes on your website. The easiest way to do this is using an `<audio>` tag. `jekyll-podcast` provides a liquid filter called `episode_url`, which will add the correct URL to the filename you provide in your front matter.
188
+
189
+ Here's an example.
190
+
191
+ ```html
192
+ <!-- _includes/audio-player.html -->
193
+
194
+ <audio controls preload="metadata" src="{{ post.podcast.file | episode_url }}"></audio>
195
+ ```
196
+
197
+ ### Podcast data
198
+
199
+ While `jekyll-podcast` is analysing your podcast files, it collects some interesting information about your podcast, and logs it to screen as part of the build process. This information includes the number of episodes, their total size in megabytes and their total duration (to the nearest millisecond).
200
+
201
+ ```shell
202
+ 236 episodes; 15786.9 MB; 9 d 16 h 6 min 25.577 s
203
+ ```
204
+
205
+ ### Contributor pages
206
+
207
+ `jekyll-podcasts` has a feature which allows you to create bio pages for each of your contributors. These pages can include whatever information you like, including a chronological list of all of the episodes that a contributor has appeared in.
208
+
209
+ To get this to work, you need to create a Jekyll collection for your contributor pages. To do this, add a block like this to `_config.yml`.
210
+
211
+ ```yaml
212
+ # _config.yml
213
+
214
+ collections:
215
+ contributors:
216
+ output: true
217
+ permalink: /contributors/:slug/
218
+ ```
219
+
220
+ Then create a layout for your contributor pages, and specify it as a default in `_config.yml`.
221
+
222
+ ```yaml
223
+ # _config.yml
224
+
225
+ defaults:
226
+ - scope:
227
+ path: ""
228
+ type: contributors
229
+ values:
230
+ layout: contributors-page
231
+ ```
232
+
233
+ This layout should include the page content, and then iterate through the contributor's posts, which are all accessible to the layout and the page as `{{ page.posts }}`. Here's a simple example.
234
+
235
+ ```html
236
+ <!-- contributors-page.html -->
237
+
238
+ <h1>page.title</h1>
239
+
240
+ {{ content }}
241
+
242
+ {% for post in page.posts %}
243
+ <article>
244
+ <h1>{{ post.title }}</h1>
245
+ {{ post.content }}
246
+ </article>
247
+ {% endfor %}
248
+ ```
249
+
250
+ Now you can create the contributor's pages. Each page can contain a picture, a bio and anything else you want. So long as you set the layout in the front matter to `contributors-page`, the pages will display all of the episodes that the contributor is involved in.
251
+
252
+ To indicate which contributors are involved in a particular episode, just add a list of contributors to the front matter of the corresponding post.
253
+
254
+ ```yaml
255
+ contributors:
256
+ - Jonathan Archer
257
+ - Gabriel Lorca
258
+ - Christopher Pike
259
+ - James T Kirk
260
+ ```
261
+
262
+ > Originally this feature was called _Guest pages_, and it's still possible to call this feature whatever you want. Just provide an replacement name in plural form to the `podcast` block in `_config.yml` as the `contributors_alias`, like this:
263
+ >
264
+ >```yaml
265
+ > # _config.yml
266
+ >
267
+ > podcast:
268
+ > contributors_alias: guests
269
+ > ```
270
+ >
271
+ > If you do this, you should also change the name of the collection and the default type in `_config.yml` as shown above.
272
+
273
+ ### Tag pages
274
+
275
+ There are plenty of other implementations of tag pages for Jekyll blogs, and so this one just aims to be as simple as possible.
276
+
277
+ To specify an episode's tags, just list them in the post's front matter.
278
+
279
+ ```yaml
280
+ tags:
281
+ - The Tenth Doctor
282
+ - Specials
283
+ - Christmas
284
+ ```
285
+
286
+ That's it really. By default, the permalink of a tag page will be the slugified version of the tag's text.
287
+
288
+ If you want to specify permalinks for a tag, you can do that by creating a file in the data directory called `tag_permalinks.yaml` or `tag_permalinks.json`. It should be a hash, with the tag as the key and the permalink as the value.
289
+
290
+ ```yaml
291
+ # tag_permalinks.yaml
292
+
293
+ "Star Trek: The Next Generation": /tng/
294
+ "Star Trek: Deep Space Nine": /ds9/
295
+ "Star Trek: Voyager": /voy/
296
+ ```
297
+
298
+ To create a list of tag links attached to a post, you can use `jekyll-podcast`'s `tag_link` filter, like this.
299
+
300
+ ```html
301
+ {% for tag in post.tags %}
302
+ {{ tag | tag_link }}
303
+ {% endfor %}
304
+ ```
305
+
306
+ ### The `pagetitle` tag
307
+
308
+ The `{% pagetitle %}` Liquid tag can be placed in the `<head>` of your HTML layouts, and it will render a `<title>` tag for your page. This tag will consist of the title of your page (as specified in the front matter), followed by an em-dash, followed by the title of your site (as specified in `_config.yml`). If your page has no title or if its title is the same as your site's title, the tag will just contain your site's title.
309
+
310
+ ### `jekyll-podcast` in action
311
+
312
+ I've been using `jekyll-podcast` to create podcast websites since the middle of 2021, after hosting podcasts with WordPress for a number of years. It has allowed me to take more control of my podcast sites, and to spend my time writing HTML and Sass (and Ruby, I guess) instead of wrestling with WordPress plugins and PHP.
313
+
314
+ If you would like to see some podcasts powered by `jekyll-podcast`, here's a list of the podcasts I'm currently running.
315
+
316
+ - [Flight Through Entirety](https://flightthroughentirety.com), a _Doctor Who_ podcast flying through the entirety of the show's 60-year history.
317
+ - [Bondfinger](https://bondfinger.com), a James Bond commentary podcast that has run out of James Bond films and now spends its time drinking and watching terrible TV shows from the 1960s mostly.
318
+ - [Jodie into Terror](https://jodieintoterror.com), a _Doctor Who_ flashcast in which we give our (intermittently) enthusiastic hot takes on the most recent era of _Doctor Who_ mere days after each episode's first broadcast in the UK.
319
+ - [Untitled Star Trek Project](https://untitledstartrekproject.com), a _Star Trek_ commentary podcast in which two friends watch _Star Trek_ episodes from any series, chosen (nearly) at random by [a page on the podcast website](https://untitledstartrekproject.com/randomiser).
320
+
321
+ <!--
322
+ ## Development
323
+
324
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
325
+
326
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
327
+
328
+ ## Contributing
329
+
330
+ Bug reports and pull requests are welcome on GitHub at <https://github.com/furius95/jekyll-podcast>.
331
+
332
+ -->
333
+ ## License
334
+
335
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ require 'rubocop/rake_task'
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: %i[spec rubocop]
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/jekyll/podcast/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'jekyll-podcast'
7
+ spec.version = Jekyll::Podcast::VERSION
8
+ spec.authors = ['Nathan Bottomley']
9
+ spec.email = ['nathan.bottomley@gmail.com']
10
+
11
+ spec.summary = 'A Jekyll plugin that provides some useful features for podcasting websites.'
12
+ spec.homepage = 'https://github.com/furius95/jekyll-podcast'
13
+ spec.license = 'MIT'
14
+ spec.required_ruby_version = '>= 3.0.0'
15
+
16
+ # spec.metadata['allowed_push_host'] = 'http://mygemserver.com'
17
+
18
+ spec.metadata['homepage_uri'] = spec.homepage
19
+ spec.metadata['source_code_uri'] = spec.homepage
20
+ # spec.metadata['changelog_uri'] = 'TODO: Put your gem's CHANGELOG.md URL here.'
21
+
22
+ # Specify which files should be added to the gem when it is released.
23
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
24
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
25
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
26
+ end
27
+ # spec.bindir = 'exe'
28
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
29
+ spec.require_paths = ['lib']
30
+
31
+ spec.add_runtime_dependency 'jekyll', '~> 4.2'
32
+ spec.add_runtime_dependency 'json-schema', '~> 2.6'
33
+ spec.add_runtime_dependency 'mp3info', '~> 0.8.5'
34
+
35
+ spec.add_development_dependency 'nokogiri', '~> 1.13'
36
+ spec.metadata['rubygems_mfa_required'] = 'true'
37
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module Podcast
5
+ module ContributorPageGenerator
6
+ # Adds posts to each contributor page on the site
7
+ class Generator < Jekyll::Generator
8
+ def generate(site)
9
+ @site = site
10
+ collect_contributor_posts
11
+ @site.documents.each do |doc|
12
+ next unless doc.type == contributors_alias.to_sym
13
+
14
+ doc.data['posts'] = @contributor_posts[doc.data['title']]
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def collect_contributor_posts
21
+ @contributor_posts = {}
22
+ @site.posts.docs.each do |post|
23
+ next unless post.data[contributors_alias]
24
+
25
+ post.data[contributors_alias].each do |contributor|
26
+ @contributor_posts[contributor] ||= []
27
+ @contributor_posts[contributor].push(post)
28
+ end
29
+ end
30
+ end
31
+
32
+ def contributors_alias
33
+ @site.config['podcast']['contributors_alias'] || 'contributors'
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ # Define duration method in Jekyll::Podcast to convert from seconds to string for feed
5
+ module Podcast
6
+ # Class responsible for setting episode data on a post's page
7
+ class EpisodeData
8
+ def initialize(page, payload)
9
+ @site = page.site
10
+ @page = payload['page']
11
+ @file_path = File.join(Jekyll::Podcast::Utils.episodes_dir(@site), @page['podcast']['file'])
12
+ end
13
+
14
+ def add_episode_data
15
+ @page['podcast'].merge!({ 'size' => size,
16
+ 'size_in_megabytes' => size_in_megabytes,
17
+ 'duration' => duration(seconds),
18
+ 'guid' => guid })
19
+ end
20
+
21
+ def size
22
+ if File.exist? @file_path
23
+ File.size(@file_path)
24
+ else
25
+ 0
26
+ end
27
+ end
28
+
29
+ def size_in_megabytes
30
+ "#{(size / 1_000_000.0).round(1)} MB"
31
+ end
32
+
33
+ def seconds
34
+ if File.exist? @file_path
35
+ Mp3Info.open(@file_path, &:length)
36
+ else
37
+ 0
38
+ end
39
+ end
40
+
41
+ def duration(seconds)
42
+ format('%<hours>d:%<minutes>02d:%<seconds>02d',
43
+ Jekyll::Podcast::Utils.duration(seconds))
44
+ end
45
+
46
+ def guid
47
+ @page['podcast']['guid'] || "#{@site.config['url']}#{@page['url']}"
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ Jekyll::Hooks.register :posts, :pre_render, priority: 'high' do |page, payload|
54
+ Jekyll::Podcast::EpisodeData.new(page, payload).add_episode_data
55
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ Jekyll::Hooks.register :site, :after_init do |site|
4
+ required_keys = %w[title subtitle author description language summary owner email explicit category]
5
+ missing_keys = required_keys.reject { |x| site.config['podcast'].key?(x) }
6
+ Jekyll.logger.warn "Podcast config is missing keys #{missing_keys}" unless missing_keys.empty?
7
+ end
8
+
9
+ module Jekyll
10
+ module Podcast
11
+ # Class representing feed page
12
+ class FeedPage < Jekyll::Page
13
+ def read_yaml(*)
14
+ @data ||= {} # rubocop:disable Naming/MemoizedInstanceVariableName
15
+ end
16
+ end
17
+
18
+ # Generator for podcast feed
19
+ class FeedGenerator < Jekyll::Generator
20
+ def generate(site)
21
+ @site = site
22
+ site.pages << new_feed_page
23
+ end
24
+
25
+ def new_feed_page
26
+ feed_page = FeedPage.new(@site, __dir__, '', 'feed/podcast')
27
+ template_path = File.expand_path('podcast.xml', __dir__)
28
+ feed_page.content = File.read(template_path)
29
+ feed_page.data['layout'] = nil
30
+ feed_page
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module Podcast
5
+ # Liquid tag to determine the existence of a file
6
+ # Path name should be the root of the directory, without an initial slash
7
+ class FileExistsTag < Liquid::Tag
8
+ def initialize(tag_name, path, tokens)
9
+ super
10
+ @path = path
11
+ end
12
+
13
+ def render(context)
14
+ # Pipe parameter through Liquid to make additional replacements possible
15
+ url = Liquid::Template.parse(@path).render context
16
+
17
+ # Add the site source, so that it also works with a custom one
18
+ site_source = context.registers[:site].config['source']
19
+ file_path = "#{site_source}/#{url}"
20
+
21
+ # Check if file exists (returns true or false)
22
+ File.exist?(file_path.strip!).to_s
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ Liquid::Template.register_tag('file_exists', Jekyll::Podcast::FileExistsTag)
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'erb'
4
+
5
+ module Jekyll
6
+ module Podcast
7
+ # Define tag filters for podcasting
8
+ module TagFilters
9
+ def without_index_html(input)
10
+ input.delete_suffix('index.html')
11
+ end
12
+
13
+ def tag_permalink(input)
14
+ site.data['tag_permalinks'][input]
15
+ end
16
+
17
+ def episode_url(input)
18
+ input = ERB::Util.url_encode(input)
19
+ File.join(url_prefix, input)
20
+ end
21
+
22
+ private
23
+
24
+ def url_prefix
25
+ if tracking_prefix && remote_episode_host
26
+ url_prefix_with_tracking_prefix_and_remote_episode_host
27
+ elsif tracking_prefix
28
+ url_prefix_with_tracking_prefix_and_no_remote_episode_host
29
+ elsif remote_episode_host
30
+ url_prefix_with_no_tracking_prefix_and_remote_episode_host
31
+ else
32
+ File.join(site.config['url'], 'assets', 'episodes')
33
+ end
34
+ end
35
+
36
+ def url_prefix_with_tracking_prefix_and_remote_episode_host
37
+ File.join(tracking_prefix, remote_episode_host.sub(%r{^https?://}, ''))
38
+ end
39
+
40
+ def url_prefix_with_tracking_prefix_and_no_remote_episode_host
41
+ File.join(tracking_prefix, 'assets', 'episodes')
42
+ end
43
+
44
+ def url_prefix_with_no_tracking_prefix_and_remote_episode_host
45
+ remote_episode_host
46
+ end
47
+
48
+ def tracking_prefix
49
+ @context.registers[:site].config['podcast']['tracking_prefix']
50
+ end
51
+
52
+ def remote_episode_host
53
+ @context.registers[:site].config['podcast']['remote_episode_host']
54
+ end
55
+
56
+ def site
57
+ @context.registers[:site]
58
+ end
59
+ end
60
+ end
61
+ end
62
+
63
+ Liquid::Template.register_filter(Jekyll::Podcast::TagFilters)
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module Podcast
5
+ # Liquid tag for generating a page title
6
+ class PageTitleTag < Liquid::Tag
7
+ def render(context)
8
+ site_title = context.registers[:site].config['title']
9
+ page_title = context.registers[:page]['title']
10
+
11
+ if page_title.nil? || page_title.empty? || page_title == site_title
12
+ "<title>#{site_title}</title>"
13
+ else
14
+ "<title>#{page_title} — #{site_title}</title>"
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+
21
+ Liquid::Template.register_tag('pagetitle', Jekyll::Podcast::PageTitleTag)
@@ -0,0 +1,71 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <rss version="2.0"
3
+ xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
4
+ xmlns:atom="http://www.w3.org/2005/Atom"
5
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
6
+ xmlns:content="http://purl.org/rss/1.0/modules/content/">
7
+ <channel>
8
+ <title>{{ site.podcast.title }}</title>
9
+ <itunes:subtitle>{{ site.podcast.subtitle }}</itunes:subtitle>
10
+ <link>{{ site.url }}</link>
11
+ <atom:link href="{{ site.url }}{{ page.url }}" rel="self" type="application/rss+xml" />
12
+ <dc:creator><![CDATA[{{ site.podcast.author }}]]></dc:creator>
13
+ <description>{{ site.podcast.description }}</description>
14
+ <lastBuildDate>{{ site.time | date_to_rfc822 }}</lastBuildDate>
15
+ <language>{{ site.podcast.language }}</language>
16
+ <copyright>© {{ site.time | date: "%Y" }} {{ site.podcast.author }}</copyright>
17
+ <itunes:author>{{ site.podcast.author }}</itunes:author>
18
+ <itunes:type>episodic</itunes:type>
19
+ <itunes:summary>{{ site.podcast.summary }}</itunes:summary>
20
+ <itunes:owner>
21
+ <itunes:name>{{ site.podcast.owner }}</itunes:name>
22
+ <itunes:email>{{ site.podcast.email }}</itunes:email>
23
+ </itunes:owner>
24
+ <itunes:explicit>{{ site.podcast.explicit }}</itunes:explicit>
25
+ {% if site.podcast.subcategory -%}
26
+ <itunes:category text="{{ site.podcast.category }}">
27
+ <itunes:category text="{{ site.podcast.subcategory }}"/>
28
+ </itunes:category>
29
+ {%- else -%}
30
+ <itunes:category text="{{ site.podcast.category }}" />
31
+ {%- endif %}
32
+ <itunes:image href="{{ site.url }}/assets/images/podcast-logo.jpeg" />
33
+ {% if site.podcast.complete -%}
34
+ <itunes:complete>Yes</itunes:complete>
35
+ {%- endif %}
36
+ {% if site.podcast.new-feed-url -%}
37
+ <generator>Jekyll v{{ jekyll.version }}</generator>
38
+ {% for post in site.posts -%}
39
+ <item>
40
+ <title>{{ post.title }}</title>
41
+ <link>{{ site.url }}{{ post.url }}</link>
42
+ <pubDate>{{ post.date | date_to_rfc822 }}</pubDate>
43
+ <guid isPermaLink="false">{{ post.podcast.guid }}</guid>
44
+ <dc:creator><![CDATA[{{ site.podcast.author }}]]></dc:creator>
45
+ {%- capture post_feed_content_exists -%}
46
+ {%- file_exists _includes/post-feed-content.html -%}
47
+ {%- endcapture %}
48
+ {%- capture content %}
49
+ {%- if post_feed_content_exists == "true" -%}
50
+ {%- include post-feed-content.html post=post -%}
51
+ {%- else -%}
52
+ {{ post.content }}
53
+ {%- endif -%}
54
+ {%- endcapture -%}
55
+ <description><![CDATA[{{ content }}]]></description>
56
+ <content:encoded><![CDATA[{{ content }}]]></content:encoded>
57
+ <itunes:subtitle><![CDATA[{{ post.excerpt | strip_html | truncate: 250 }}]]></itunes:subtitle>
58
+ <itunes:keywords>{{ post.tags | join: ","}}</itunes:keywords>
59
+ <itunes:episodeType>full</itunes:episodeType>
60
+ <itunes:title>{{ post.title }}</itunes:title>
61
+ <itunes:episode>{{ post.podcast.episode }}</itunes:episode>
62
+ <enclosure url="{{ post.podcast.file | episode_url }}" length="{{ post.podcast.size }}"
63
+ type="audio/mpeg" />
64
+ <itunes:summary><![CDATA[{{ post.excerpt | strip_html }}]]></itunes:summary>
65
+ <itunes:block>no</itunes:block>
66
+ <itunes:duration>{{ post.podcast.duration }}</itunes:duration>
67
+ <itunes:author>{{ site.podcast.author }}</itunes:author>
68
+ </item>
69
+ {% endfor %}
70
+ </channel>
71
+ </rss>
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module Podcast
5
+ # Calculate the total count and duration of all podcast episodes
6
+ module PodcastData
7
+ class << self
8
+ def episodes_dir
9
+ Jekyll::Podcast::Utils.episodes_dir(@site)
10
+ end
11
+
12
+ def episodes
13
+ Dir.children(episodes_dir).select { |x| x.end_with?('.mp3') }
14
+ end
15
+
16
+ def total_duration_in_seconds
17
+ episodes.sum do |mp3|
18
+ Mp3Info.open(File.join(episodes_dir, mp3), &:length)
19
+ end
20
+ end
21
+
22
+ def total_size_in_megabytes
23
+ size_in_bytes = episodes.sum do |mp3|
24
+ File.size(File.join(episodes_dir, mp3))
25
+ end
26
+ "#{(size_in_bytes / 1_000_000.0).round(1)} MB"
27
+ end
28
+
29
+ def podcast_data
30
+ result = Jekyll::Podcast::Utils.duration(total_duration_in_seconds)
31
+ result[:count] = episodes.length
32
+ result[:size] = total_size_in_megabytes
33
+ result
34
+ end
35
+
36
+ def podcast_data_log_entry(site)
37
+ @site = site
38
+ if Dir.exist?(episodes_dir)
39
+ format(
40
+ '%<count>d episodes; %<size>s;' \
41
+ '%<days>d d %<hours>d h %<minutes>d min %<seconds>0.3f s',
42
+ podcast_data
43
+ )
44
+ else
45
+ "No episodes directory found at #{episodes_dir}"
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ Jekyll::Hooks.register :site, :post_write do |site|
54
+ Jekyll.logger.info Jekyll::Podcast::PodcastData.podcast_data_log_entry(site).yellow
55
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module Drops
5
+ # A new :podcast_element component for the site's permalink structure
6
+ class UrlDrop < Drop
7
+ def podcast_episode
8
+ @obj.data.dig('podcast', 'episode').to_s
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module Podcast
5
+ # creates a filter to turn tag names into links
6
+ module TagLinkFilter
7
+ def tag_link(input)
8
+ tag_href = Jekyll::Podcast::TagPageGenerator.permalink(input, @context.registers[:site])
9
+ "<a class='tag' href='#{tag_href}'>#{input}</a>"
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+ Liquid::Template.register_filter(Jekyll::Podcast::TagLinkFilter)
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module Podcast
5
+ # Generator to create tag pages for each tag on the site
6
+ module TagPageGenerator
7
+ # The generator itself
8
+ class Generator < Jekyll::Generator
9
+ def generate(site)
10
+ site.tags.each do |tag, _|
11
+ site.pages << TagPage.new(site, tag)
12
+ end
13
+ end
14
+ end
15
+
16
+ # Represents a tag page; includes pagination information
17
+ class TagPage < Jekyll::Page
18
+ def initialize(site, tag)
19
+ super(site, site.baseurl, '/', 'index.html')
20
+ @tag = tag
21
+ @data ||= {}
22
+ @data['permalink'] = Jekyll::Podcast::TagPageGenerator.permalink(@tag, site)
23
+ @data['layout'] = 'tag-page'
24
+ @data['title'] = tag
25
+ @data['pagination'] = pagination(site)
26
+ end
27
+
28
+ def pagination(site)
29
+ pagination_config = site.config.dig('tag_pages', 'pagination') || {}
30
+ {
31
+ 'enabled' => true,
32
+ 'tag' => @tag,
33
+ 'sort_reverse' => false
34
+ }.merge(pagination_config)
35
+ end
36
+ end
37
+
38
+ def self.permalink(tag, site)
39
+ if site.data['tag_permalinks'] && site.data['tag_permalinks'][tag]
40
+ site.data['tag_permalinks'][tag]
41
+ else
42
+ "/#{Jekyll::Utils.slugify(tag)}/"
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module Podcast
5
+ # Utility functions used in jekyll-podcast
6
+ module Utils
7
+ class << self
8
+ def duration(seconds)
9
+ mm, ss = seconds.divmod(60)
10
+ hh, mm = mm.divmod(60)
11
+ dd, hh = hh.divmod(24)
12
+ {
13
+ days: dd,
14
+ hours: hh,
15
+ minutes: mm,
16
+ seconds: ss
17
+ }
18
+ end
19
+
20
+ def episodes_dir(site)
21
+ if site.config['podcast']['remote_episode_host']
22
+ File.join(site.source, '_episodes')
23
+ else
24
+ File.join(site.source, 'assets/episodes')
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'date'
4
+ require 'yaml'
5
+ require 'json'
6
+ require 'json-schema'
7
+
8
+ module Jekyll
9
+ module Podcast
10
+ # Validate the frontmatter of each document using schemas in the _schemas directory
11
+ module ValidateYAMLFrontmatter
12
+ class << self
13
+ date_proc = lambda { |value|
14
+ begin
15
+ Date.iso8601(value)
16
+ rescue ArgumentError
17
+ raise JSON::Schema::CustomFormatError, 'must be in ISO-8601 format: CCYY-MM-DD'
18
+ end
19
+ }
20
+ JSON::Validator.register_format_validator('full-date', date_proc)
21
+
22
+ def print_validation_complete_message(error_count)
23
+ if error_count.zero?
24
+ Jekyll.logger.info 'YAML frontmatter validated successfully'.yellow
25
+ else
26
+ Jekyll.logger.info "YAML frontmatter validation failed with #{error_count} errors".yellow
27
+ end
28
+ end
29
+
30
+ def print_document_validation_failed_message(document, errors)
31
+ Jekyll.logger.info "Validation failed for #{document.path}:".yellow
32
+ Jekyll.logger.info(errors.map { |x| "- #{x}" }.join("\n").yellow)
33
+ end
34
+
35
+ def validate_document(document)
36
+ return [] unless File.exist? "_schemas/#{document.collection.label}.json"
37
+
38
+ document_frontmatter = YAML.safe_load_file(document.path, permitted_classes: [Date]).to_json
39
+ JSON::Validator.fully_validate("_schemas/#{document.collection.label}.json", document_frontmatter)
40
+ end
41
+
42
+ def validate_site(site)
43
+ Jekyll.logger.info 'Validating YAML frontmatter'.yellow
44
+ error_count = 0
45
+ site.documents.each do |document|
46
+ result = validate_document(document)
47
+ next if result.empty?
48
+
49
+ error_count += result.length
50
+ print_document_validation_failed_message(document, result)
51
+ end
52
+ print_validation_complete_message(error_count)
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ Jekyll::Hooks.register :site, :pre_render do |site, _payload|
60
+ Jekyll::Podcast::ValidateYAMLFrontmatter.validate_site(site)
61
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module Podcast
5
+ VERSION = '0.9.0'
6
+ end
7
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'jekyll'
4
+ require 'mp3info'
5
+ require 'json-schema'
6
+
7
+ require 'jekyll/podcast/version'
8
+
9
+ module Jekyll
10
+ module Podcast
11
+ class Error < StandardError; end
12
+ end
13
+ end
14
+
15
+ require 'jekyll/podcast/utils'
16
+ require 'jekyll/podcast/episode_data'
17
+ require 'jekyll/podcast/podcast_episode_drop'
18
+ require 'jekyll/podcast/liquid_tag_filters'
19
+ require 'jekyll/podcast/file_exists'
20
+ require 'jekyll/podcast/feed_generator'
21
+ require 'jekyll/podcast/tag_page_generator'
22
+ require 'jekyll/podcast/tag_link_filter'
23
+ require 'jekyll/podcast/contributor_page_generator'
24
+ require 'jekyll/podcast/podcast_data'
25
+ require 'jekyll/podcast/validate_yaml_frontmatter'
26
+ require 'jekyll/podcast/page_title_liquid_tag'
metadata ADDED
@@ -0,0 +1,127 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jekyll-podcast
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.0
5
+ platform: ruby
6
+ authors:
7
+ - Nathan Bottomley
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-09-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.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '4.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: json-schema
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.6'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.6'
41
+ - !ruby/object:Gem::Dependency
42
+ name: mp3info
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.8.5
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.8.5
55
+ - !ruby/object:Gem::Dependency
56
+ name: nokogiri
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.13'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.13'
69
+ description:
70
+ email:
71
+ - nathan.bottomley@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - ".rspec"
78
+ - ".rubocop.yml"
79
+ - CHANGELOG.md
80
+ - Gemfile
81
+ - Gemfile.lock
82
+ - LICENSE.txt
83
+ - README.md
84
+ - Rakefile
85
+ - jekyll-podcast.gemspec
86
+ - lib/jekyll/podcast.rb
87
+ - lib/jekyll/podcast/contributor_page_generator.rb
88
+ - lib/jekyll/podcast/episode_data.rb
89
+ - lib/jekyll/podcast/feed_generator.rb
90
+ - lib/jekyll/podcast/file_exists.rb
91
+ - lib/jekyll/podcast/liquid_tag_filters.rb
92
+ - lib/jekyll/podcast/page_title_liquid_tag.rb
93
+ - lib/jekyll/podcast/podcast.xml
94
+ - lib/jekyll/podcast/podcast_data.rb
95
+ - lib/jekyll/podcast/podcast_episode_drop.rb
96
+ - lib/jekyll/podcast/tag_link_filter.rb
97
+ - lib/jekyll/podcast/tag_page_generator.rb
98
+ - lib/jekyll/podcast/utils.rb
99
+ - lib/jekyll/podcast/validate_yaml_frontmatter.rb
100
+ - lib/jekyll/podcast/version.rb
101
+ homepage: https://github.com/furius95/jekyll-podcast
102
+ licenses:
103
+ - MIT
104
+ metadata:
105
+ homepage_uri: https://github.com/furius95/jekyll-podcast
106
+ source_code_uri: https://github.com/furius95/jekyll-podcast
107
+ rubygems_mfa_required: 'true'
108
+ post_install_message:
109
+ rdoc_options: []
110
+ require_paths:
111
+ - lib
112
+ required_ruby_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: 3.0.0
117
+ required_rubygems_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ requirements: []
123
+ rubygems_version: 3.3.7
124
+ signing_key:
125
+ specification_version: 4
126
+ summary: A Jekyll plugin that provides some useful features for podcasting websites.
127
+ test_files: []