woody 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in podgen.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 David Robertson
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,21 @@
1
+ # Woody
2
+
3
+ Podcast static site generator
4
+
5
+ ## Installation
6
+
7
+ To install, run this:
8
+
9
+ $ gem install woody
10
+
11
+ ## Usage
12
+
13
+ TODO: Write usage instructions here
14
+
15
+ ## Contributing
16
+
17
+ 1. Fork it
18
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
19
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
20
+ 4. Push to the branch (`git push origin my-new-feature`)
21
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/woody ADDED
@@ -0,0 +1,58 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ require 'woody'
4
+ require 'commander/import'
5
+
6
+ puts
7
+ puts
8
+ puts
9
+
10
+ program :name, 'woody'
11
+ program :version, Woody::VERSION
12
+ program :description, 'Podcast static site generator'
13
+
14
+
15
+ command :compile do |c|
16
+ c.description = "Compiles the site"
17
+ c.action do |args, options|
18
+ Woody.init
19
+ Woody.compile
20
+ end
21
+ end
22
+
23
+ command :deploy do |c|
24
+ c.description = "Deploys the site"
25
+ c.action do |args, options|
26
+ Woody.init
27
+ Woody.deploy
28
+ end
29
+ end
30
+
31
+ command :cd do |c|
32
+ c.description = "Compiles then deploys the site"
33
+ c.action do |args, options|
34
+ Woody.init
35
+ Woody.compile
36
+ Woody.deploy
37
+ end
38
+ end
39
+
40
+ command :new do |c|
41
+ c.description = "Creates a blank Woody site with some defaults"
42
+ c.syntax = "new [sitename]"
43
+ c.action do |args, options|
44
+ if args[0].nil? or !(args[0].is_a? String)
45
+ puts "Syntax: woody new [sitename]"
46
+ exit!
47
+ end
48
+ Woody::new_site(args[0])
49
+ end
50
+ end
51
+
52
+ command :update_templates do |c|
53
+ c.description = "Sets template files to current default. DESTRUCTIVE!"
54
+ c.action do |args, options|
55
+ Woody.init
56
+ Woody::update_templates
57
+ end
58
+ end
@@ -0,0 +1,3 @@
1
+ module Woody
2
+ VERSION = "0.0.7"
3
+ end
data/lib/woody.rb ADDED
@@ -0,0 +1,306 @@
1
+ require "woody/version"
2
+
3
+ require 'yaml'
4
+ require 'erubis'
5
+ require 'mp3info'
6
+ require 'aws/s3'
7
+ require 'digest'
8
+ require 'fileutils'
9
+
10
+
11
+ module Woody
12
+ $source_root = File.expand_path("../../templates", __FILE__)
13
+
14
+ # Load configuration
15
+ def self.init
16
+ begin
17
+ $config = YAML.load_file("woody-config.yml")
18
+ rescue Errno::ENOENT
19
+ puts "This doesn't look like a valid Woody site directory!"
20
+ return
21
+ end
22
+
23
+ AWS::S3::Base.establish_connection!(
24
+ :access_key_id => $config['s3']['accesskey']['id'],
25
+ :secret_access_key => $config['s3']['accesskey']['secret']
26
+ )
27
+ AWS::S3::DEFAULT_HOST.replace $config['s3']['hostname']
28
+ $bucketname = $config['s3']['bucket']
29
+ $itunes_image_url = "FILL IN URL"
30
+ end
31
+
32
+ def self.new_site(name)
33
+ puts "Creating new site '#{name}'..."
34
+ if File.directory?(name)
35
+ puts "Error: directory '#{name}' already exists!"
36
+ return false
37
+ end
38
+
39
+ cdir_p(name)
40
+ cpy_t("woody-config.yml", "#{name}/woody-config.yml")
41
+
42
+ cdir_p("#{name}/templates")
43
+ cpy_t("layout.html", "#{name}/templates/layout.html")
44
+ cpy_t("index.html", "#{name}/templates/index.html")
45
+ cpy_t("episode.html", "#{name}/templates/episode.html")
46
+
47
+ cdir_p("#{name}/templates/assets")
48
+ cpy_t("stylesheet.css", "#{name}/templates/assets/stylesheet.css")
49
+
50
+ cdir_p("#{name}/content")
51
+ cpy_t("metadata.yml", "#{name}/content/metadata.yml")
52
+
53
+
54
+ cdir_p("#{name}/output")
55
+ cdir_p("#{name}/output/assets")
56
+ cdir_p("#{name}/output/assets/mp3")
57
+ cdir_p("#{name}/output/episode")
58
+
59
+ puts "Done!"
60
+ puts "Now, do `cd #{name}` then edit the config file, woody-config.yml."
61
+ end
62
+
63
+ def self.update_templates
64
+ puts "Updating templates..."
65
+ cpy_t("layout.html", "templates/layout.html")
66
+ cpy_t("index.html", "templates/index.html")
67
+ cpy_t("episode.html", "templates/episode.html")
68
+ cpy_t("stylesheet.css", "templates/assets/stylesheet.css")
69
+ puts "Done! Thanks for updating :)"
70
+ end
71
+
72
+ def self.cdir_p(dir)
73
+ puts "Creating directory '#{dir}'"
74
+ FileUtils.mkdir_p(dir)
75
+ end
76
+ def self.cpy_t(source, destination)
77
+ puts "Creating file '#{destination}'"
78
+ FileUtils.cp File.join($source_root, source), destination
79
+ end
80
+
81
+ class Episode
82
+ def self.new_from_meta(filename, meta)
83
+ return Episode.new(filename, meta['title'], Date.parse(meta['date']), meta['synopsis'], meta['subtitle'], meta['tags'])
84
+ end
85
+ def initialize(filename, title, date, synopsis, subtitle = nil, tags = [], compiledname = nil)
86
+ @filename = filename
87
+ @title = title
88
+ @date = date
89
+ @synopsis = synopsis
90
+ @subtitle = subtitle
91
+ @tags = tags
92
+ @compiledname = compiledname
93
+
94
+ if @compiledname.nil? or @compiledname.empty?
95
+ @compiledname = @filename.gsub(/[^0-9A-Za-z .]/, '').gsub(' ','_')
96
+ end
97
+ end
98
+ attr_accessor :filename, :title, :date, :synopsis, :tags, :subtitle, :compiledname
99
+ def duration
100
+ return @duration unless @duration.nil?
101
+ length = 0
102
+ Mp3Info.open("content/#{@filename}") do |mp3|
103
+ length = mp3.length
104
+ end
105
+ length = length.to_i
106
+ seconds = length % 60
107
+ minutes = (length / 60).to_i
108
+ @duration = "#{minutes}:#{seconds}"
109
+ end
110
+ def size
111
+ File.size "content/#{filename}"
112
+ end
113
+ def keywords
114
+ @tags.join ', ' unless @tags.nil? or @tags.empty?
115
+ end
116
+ def file_path(leader=true)
117
+ return "#{leader ? "/" : ""}assets/mp3/#{@compiledname}" unless @compiledname.nil?
118
+ return false
119
+ end
120
+ def file_url
121
+ return "#{$config['urlbase']}#{file_path}" unless file_path.nil?
122
+ return false
123
+ end
124
+ def path(leader=true)
125
+ return "#{leader ? "/" : ""}episode/#{@compiledname[0..-5]}.html" unless @compiledname.nil?
126
+ return false
127
+ end
128
+ def url
129
+ return "#{$config['urlbase']}#{path}" unless path.nil?
130
+ return false
131
+ end
132
+ end
133
+
134
+ def self.compile()
135
+ puts "Compiling..."
136
+ meta = YAML.load_file("content/metadata.yml")
137
+
138
+ episodes = Array.new
139
+ filesfound = Array.new
140
+ touchedfiles = Array.new
141
+ Dir.glob('content/*.mp3') do |file|
142
+ filename = file[8..-1]
143
+ unless meta == false or meta[filename].nil?
144
+ # Episode metadata already stored
145
+ episodes << Episode.new_from_meta(filename, meta[filename])
146
+ filesfound << filename
147
+ else
148
+ # No episode metadata stored for this yet
149
+
150
+ puts "Warning: no metadata found for file #{filename}"
151
+ end
152
+ end
153
+
154
+ # Check for files in meta but not found
155
+ unless meta == false
156
+ meta.each do |file|
157
+ next if filesfound.include? file[0]
158
+ puts "Warning: found metadata for file #{file[0]}, but file itself is missing. Will not be published."
159
+ end
160
+ end
161
+
162
+ # Make sure necessary directories exist
163
+ FileUtils.mkdir_p('output/assets') unless File.directory?('output/assets')
164
+ FileUtils.mkdir_p('output/assets/mp3') unless File.directory?('output/assets/mp3')
165
+ FileUtils.mkdir_p('output/episode') unless File.directory?('output/episode')
166
+
167
+ # Copy over (TODO: and process) MP3 files
168
+ episodes.each do |episode|
169
+ FileUtils.copy "content/#{episode.filename}", "output/assets/mp3/#{episode.compiledname}"
170
+ touchedfiles << "assets/mp3/#{episode.compiledname}"
171
+ end
172
+
173
+ # Copy over assets
174
+ Dir.foreach("templates/assets") do |item|
175
+ next if item == '.' or item == '..'
176
+ begin
177
+ FileUtils.copy "templates/assets/#{item}", "output/assets/#{item}"
178
+ touchedfiles << "assets/#{item}"
179
+ rescue Errno::EISDIR
180
+ puts "Warning: subdirectories in templates/assets are ignored!"
181
+ end
182
+ end
183
+
184
+ # Update index.html
185
+ layout = File.read('templates/layout.html')
186
+ layout = Erubis::Eruby.new(layout)
187
+
188
+ index_compiled = layout.result(config: $config, episodes: episodes) do
189
+ index = Erubis::Eruby.new(File.read('templates/index.html'))
190
+ index.result(config: $config, episodes: episodes, test: "hello, world") do |episode|
191
+ ep = Erubis::Eruby.new(File.read('templates/episode.html'))
192
+ ep.result(config: $config, episodes: episodes, episode: episode)
193
+ end
194
+ end
195
+ File.open('output/index.html', 'w') {|f| f.write(index_compiled) }
196
+ touchedfiles << 'index.html'
197
+
198
+ # Update episode pages
199
+ episodes.each do |episode|
200
+ layout = File.read('templates/layout.html')
201
+ layout = Erubis::Eruby.new(layout)
202
+ episode_compiled = layout.result(config: $config, episodes: episodes) do
203
+ ep = Erubis::Eruby.new(File.read('templates/episode.html'))
204
+ ep.result(config: $config, episodes: episodes, episode: episode)
205
+ end
206
+ File.open("output/#{episode.path(false)}", 'w') {|f| f.write(episode_compiled) }
207
+ touchedfiles << episode.path(false)
208
+ end
209
+
210
+ # Update iTunes RSS
211
+ itunes = File.read "#{$source_root}/itunes.xml" # Use itunes.xml template in gem, not in site's template folder.
212
+ itunes = Erubis::Eruby.new(itunes)
213
+ itunes_compiled = itunes.result(config: $config, episodes: episodes)
214
+ File.open("output/itunes.xml", 'w') {|f| f.write(itunes_compiled) }
215
+ touchedfiles << "itunes.xml"
216
+
217
+
218
+ # Update General RSS
219
+
220
+
221
+ # Purge left over files
222
+ purge_output(touchedfiles)
223
+ end
224
+
225
+ def self.purge_output(touchedfiles, subdir = "")
226
+ Dir.foreach("output/#{subdir}") do |item|
227
+ next if item == '.' or item == '..'
228
+ p = "#{subdir}#{item}"
229
+ begin
230
+ File.delete "output/#{subdir}#{item}" unless touchedfiles.include? p
231
+ rescue Errno::EISDIR, Errno::EPERM # Rescuing EPERM seems to be necessary on macs, hmm :/
232
+ purge_output touchedfiles, "#{p}/"
233
+ end
234
+ end
235
+ end
236
+
237
+ def self.deploy
238
+ touchedfiles = Array.new
239
+ deploy_r touchedfiles
240
+
241
+ # Purge left over files
242
+ purge_bucket touchedfiles
243
+ end
244
+
245
+ def self.deploy_r(touchedfiles, subdir = "")
246
+ puts "Deploying... " if subdir == ""
247
+ Dir.foreach("output/#{subdir}") do |item|
248
+ next if item == '.' or item == '..'
249
+ begin
250
+ touchedfiles << "#{subdir}#{item}"
251
+ upload("#{subdir}#{item}", "output/#{subdir}#{item}")
252
+ rescue Errno::EISDIR
253
+ deploy_r touchedfiles, "#{subdir}#{item}/"
254
+ end
255
+ end
256
+ end
257
+
258
+ def self.purge_bucket(touchedfiles)
259
+ bucket = AWS::S3::Bucket.find $bucketname
260
+ bucket.objects.each do |object|
261
+ object.delete unless touchedfiles.include? object.key
262
+ end
263
+ end
264
+
265
+ def self.filehash(filepath)
266
+ sha1 = Digest::SHA1.new
267
+ File.open(filepath) do|file|
268
+ buffer = ''
269
+ # Read the file 512 bytes at a time
270
+ while not file.eof
271
+ file.read(512, buffer)
272
+ sha1.update(buffer)
273
+ end
274
+ end
275
+ return sha1.to_s
276
+ end
277
+
278
+ def self.upload(objectname, filepath)
279
+ # Generate hash of file
280
+ hash = filehash filepath
281
+
282
+ # Get hash of version already uploaded, if available.
283
+ begin
284
+ object = AWS::S3::S3Object.find objectname, $bucketname
285
+ oldhash = object.metadata['hash']
286
+ rescue AWS::S3::NoSuchKey
287
+ # File not uploaded yet
288
+ oldhash = nil
289
+ end
290
+ unless hash == oldhash
291
+ # Don't reupload if file hasn't changed
292
+ puts "#{objectname}: Uploading"
293
+ AWS::S3::S3Object.store(objectname, open(filepath), $bucketname, access: :public_read, 'x-amz-meta-hash' => hash)
294
+ else
295
+ puts "#{objectname}: Not uploading, hasn't changed since last time."
296
+ end
297
+ end
298
+
299
+
300
+
301
+
302
+ end
303
+
304
+ def link_to(name, url)
305
+ return %Q{<a href="#{url}">#{name}</a>}
306
+ end
@@ -0,0 +1,16 @@
1
+ <h3><%= link_to episode.title, episode.path %></h3>
2
+ <h4><%= episode.subtitle %></h4>
3
+ Player goes here
4
+
5
+ <a href="<%= episode.file_path %>">Download MP3</a>
6
+
7
+ <div class="synopsis">
8
+ <%= episode.synopsis %>
9
+ </div>
10
+
11
+ <div class="tags">
12
+ <strong>Tags:</strong>
13
+ <% episode.tags.each do |tag| %>
14
+ <span class="tag"><%= tag %> </span>
15
+ <% end %>
16
+ </div>
@@ -0,0 +1,6 @@
1
+ <h2>Episodes:</h2>
2
+ <% episodes.each do |episode| %>
3
+ <div class="episode">
4
+ <%= yield episode %>
5
+ </div>
6
+ <% end %>
@@ -0,0 +1,33 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <rss xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" version="2.0">
3
+ <channel>
4
+ <title><%= config['title'] %></title>
5
+ <link><%= config['urlbase'] %></link>
6
+ <language>en</language>
7
+ <copyright>℗ &amp; © <%= config['author'] %></copyright>
8
+ <itunes:subtitle><%= config['subtitle'] %></itunes:subtitle>
9
+ <itunes:author><%= config['author'] %></itunes:author>
10
+ <itunes:summary><%= config['itunes']['summary'] %></itunes:summary>
11
+
12
+ <itunes:owner>
13
+ <itunes:name><%= config['itunes']['owner']['name'] %></itunes:name>
14
+ <itunes:email><%= config['itunes']['owner']['email'] %></itunes:email>
15
+ </itunes:owner>
16
+
17
+ <itunes:image href="<%= $itunes_image_url %>"/>
18
+ <itunes:category text="<%= config['itunes']['category'] %>"/>
19
+
20
+ <%- episodes.each do |episode| %>
21
+ <item>
22
+ <title><%= episode.title %></title>
23
+ <itunes:subtitle><%= episode.subtitle %></itunes:subtitle>
24
+ <itunes:summary><%= episode.synopsis %></itunes:summary>
25
+ <enclosure url="<%= episode.file_url %>" length="<%= episode.size %>" type="audio/mpeg"/>
26
+ <pubDate><%= episode.date.rfc2822 %></pubDate>
27
+ <itunes:duration><%= episode.duration %></itunes:duration>
28
+ <itunes:keywords><%= episode.keywords %></itunes:keywords>
29
+ </item>
30
+ <% end %>
31
+
32
+ </channel>
33
+ </rss>
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title><%= $config['title'] %></title>
5
+ <link rel="stylesheet" type="text/css" href="/assets/stylesheet.css" />
6
+ </head>
7
+ <body>
8
+ <h1><%= link_to $config['title'], "/" %></h1>
9
+ <h2><%= $config['subtitle'] %></h2>
10
+ <hr />
11
+
12
+ <%= yield %>
13
+ </body>
14
+ </html>
@@ -0,0 +1 @@
1
+ # Fill me in!
@@ -0,0 +1,27 @@
1
+ title: Title
2
+ subtitle: Subtitle
3
+ author: Author
4
+
5
+ # Include http://, domain name, and *NO trailing slash*
6
+ urlbase: http://example.com
7
+
8
+ mp3:
9
+ # NOT YET IMPLEMENTED! Do you want to have ID3v2 tags for artist/title automatically set? N.B., may be truncated.
10
+ setartist: true
11
+ settitle: true
12
+
13
+ itunes:
14
+ summary: iTunes Summary
15
+ owner:
16
+ name: Owner
17
+ email: owner@example.com
18
+ # Category MUST be one of the ones listed here http://www.apple.com/itunes/podcasts/specs.html#categories
19
+ category: Comedy
20
+
21
+ s3:
22
+ # Set the relevant s3 endpoint here. For eu-west-1 (Ireland), use this default.
23
+ hostname: s3-eu-west-1.amazonaws.com
24
+ accesskey:
25
+ id: your-aws-access-key-id
26
+ secret: your-aws-access-key-secret
27
+ bucket: bucketname
@@ -0,0 +1,7 @@
1
+ div.episode {
2
+ border-style: solid;
3
+ border-width: 1px;
4
+ border-color: black;
5
+ padding: 10px;
6
+ margin-bottom: 10px;
7
+ }
data/woody.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'woody/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "woody"
8
+ gem.version = Woody::VERSION
9
+ gem.authors = ["David Robertson"]
10
+ gem.email = ["david@davidr.me"]
11
+ gem.description = "Woody"
12
+ gem.summary = "Podcast Static Site Generator"
13
+ gem.homepage = "https://github.com/DavidJRobertson/woody"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_runtime_dependency 'erubis'
21
+ gem.add_runtime_dependency 'mp3info'
22
+ gem.add_runtime_dependency 'aws-s3'
23
+ gem.add_runtime_dependency 'commander'
24
+
25
+ # gem.post_install_message = "This update modifies default templates. Please run `woody update_templates` in your site directory to update them. Warning: this will destroy any modifications to your templates."
26
+ end
metadata ADDED
@@ -0,0 +1,127 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: woody
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.7
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - David Robertson
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-12-08 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: erubis
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: mp3info
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: aws-s3
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: commander
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ description: Woody
79
+ email:
80
+ - david@davidr.me
81
+ executables:
82
+ - woody
83
+ extensions: []
84
+ extra_rdoc_files: []
85
+ files:
86
+ - .gitignore
87
+ - Gemfile
88
+ - LICENSE.txt
89
+ - README.md
90
+ - Rakefile
91
+ - bin/woody
92
+ - lib/woody.rb
93
+ - lib/woody/version.rb
94
+ - templates/episode.html
95
+ - templates/index.html
96
+ - templates/itunes.xml
97
+ - templates/layout.html
98
+ - templates/metadata.yml
99
+ - templates/podgen-config.yml
100
+ - templates/stylesheet.css
101
+ - woody.gemspec
102
+ homepage: https://github.com/DavidJRobertson/woody
103
+ licenses: []
104
+ post_install_message:
105
+ rdoc_options: []
106
+ require_paths:
107
+ - lib
108
+ required_ruby_version: !ruby/object:Gem::Requirement
109
+ none: false
110
+ requirements:
111
+ - - ! '>='
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ required_rubygems_version: !ruby/object:Gem::Requirement
115
+ none: false
116
+ requirements:
117
+ - - ! '>='
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ requirements: []
121
+ rubyforge_project:
122
+ rubygems_version: 1.8.24
123
+ signing_key:
124
+ specification_version: 3
125
+ summary: Podcast Static Site Generator
126
+ test_files: []
127
+ has_rdoc: