woody 0.3.4 → 0.4.0

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/bin/woody CHANGED
@@ -10,12 +10,17 @@ program :description, 'Podcast static site generator'
10
10
 
11
11
  default_command :compile
12
12
 
13
+ $dir = "."
14
+ global_option '--dir', '--dir path/to/site', "Specifies path to Woody site directory, if not the current directory" do |dir|
15
+ $dir = dir
16
+ end
17
+
13
18
  command :compile do |c|
14
19
  c.description = "Compiles the site"
15
20
  c.option "--no-add", "Don't ask to add new metadata"
16
21
  c.action do |args, options|
17
- Woody.init
18
- Woody::Compiler.compile(options)
22
+ site = Woody.new($dir)
23
+ site.compile(options)
19
24
  end
20
25
  end
21
26
  alias_command :c, :compile
@@ -23,8 +28,8 @@ alias_command :c, :compile
23
28
  command :deploy do |c|
24
29
  c.description = "Deploys the site"
25
30
  c.action do |args, options|
26
- Woody.init
27
- Woody::Deployer.deploy
31
+ site = Woody.new($dir)
32
+ site.deploy
28
33
  end
29
34
  end
30
35
  alias_command :d, :deploy
@@ -33,9 +38,9 @@ command :cd do |c|
33
38
  c.description = "Compiles then deploys the site"
34
39
  c.option "--no-add", "Don't ask to add new metadata"
35
40
  c.action do |args, options|
36
- Woody.init
37
- Woody::Compiler.compile(options)
38
- Woody::Deployer.deploy
41
+ site = Woody.new($dir)
42
+ site.compile(options)
43
+ site.deploy
39
44
  end
40
45
  end
41
46
 
@@ -54,8 +59,8 @@ end
54
59
  command :'update templates' do |c|
55
60
  c.description = "Sets template files to current default. DESTRUCTIVE!"
56
61
  c.action do |args, options|
57
- Woody.init
58
- Woody::Generator.update_templates
62
+ site = Woody.new($dir)
63
+ site.update_templates
59
64
  end
60
65
  end
61
66
  alias_command :'templates update', :'update templates'
@@ -1,38 +1,48 @@
1
- module Woody
1
+ require 'preamble'
2
+
3
+ class Woody
2
4
  # Handles functions related to compiling the Woody site
3
5
  module Compiler
4
- @@touchedfiles = []
5
6
 
6
7
  # Compiles the Woody site
7
- def self.compile(options = [])
8
+ def compile(options = nil)
8
9
  puts "Compiling..."
9
- meta = YAML.load_file("content/metadata.yml")
10
+ meta = YAML.load_file(dir("content/metadata.yml"))
10
11
 
11
12
  # instantiate the metadata hash so shit doesn't explode in our faces
12
- # WEIRD SHIT: used .empty? here before but fails if used on hash seemingly
13
- if meta == false
14
- meta = Hash.new
15
- end
13
+ meta = Hash.new if meta == false
16
14
 
17
- episodes = Array.new
18
- filesfound = Array.new
19
- Dir.glob('content/*.mp3') do |file|
20
- filename = file[8..-1]
15
+ posts = Array.new
16
+ filesfound = Array.new
17
+ Dir.glob(dir('content/*.mp3')) do |file|
18
+ filename = undir(file)[8..-1]
21
19
  unless meta == false or meta[filename].nil?
22
20
  # Episode metadata already stored
23
- episodes << Episode.new_from_meta(filename, meta[filename])
21
+ posts << Episode.new_from_meta(self, filename, meta[filename])
24
22
  filesfound << filename
25
23
  else
26
24
  # No episode metadata stored for this yet
27
- unless options.no_add == false # Seemingly backwards, I know...
28
- prompt_metadata(meta, episodes, filesfound, filename)
25
+ unless options.nil? or options.no_add == false # Seemingly backwards, I know...
26
+ prompt_metadata(meta, posts, filesfound, filename)
29
27
  else
30
28
  puts "Warning: found media file #{filename} but no metadata. Will not be published."
31
29
  end
32
30
  end
33
31
  end
34
32
 
35
- episodes.sort!
33
+ # Process blog posts
34
+ Dir.glob(dir('content/posts/*')) do |file|
35
+ filename = undir(file)[8..-1]
36
+ data = Preamble.load(file)
37
+ m = data[0]
38
+ body = data[1]
39
+
40
+ posts << Post.new(self, filename, m['title'], m['subtitle'], body, Date.parse(m['date'].to_s), m['tags'])
41
+ end
42
+
43
+ posts.sort_by! do |post|
44
+ post.date
45
+ end.reverse!
36
46
 
37
47
  # Check for files in meta but not found
38
48
  unless meta.empty?
@@ -43,40 +53,41 @@ module Woody
43
53
  end
44
54
 
45
55
  # Make sure necessary directories exist
46
- FileUtils.mkdir_p('output/assets') unless File.directory?('output/assets')
47
- FileUtils.mkdir_p('output/assets/mp3') unless File.directory?('output/assets/mp3')
48
- FileUtils.mkdir_p('output/episode') unless File.directory?('output/episode')
56
+ FileUtils.mkdir_p(dir 'output/assets') unless File.directory?(dir 'output/assets')
57
+ FileUtils.mkdir_p(dir 'output/assets/mp3') unless File.directory?(dir 'output/assets/mp3')
58
+ FileUtils.mkdir_p(dir 'output/post') unless File.directory?(dir 'output/post')
49
59
 
50
60
  # Copy over (TODO: and process) MP3 files
51
- episodes.each do |episode|
52
- copy_file_to_output File.join("content", episode.filename), File.join("assets/mp3", episode.compiledname)
61
+ posts.each do |post|
62
+ next unless post.has_file?
63
+ copy_file_to_output dir(File.join("content", post.filename)), File.join("assets/mp3", post.compiledname)
53
64
  end
54
65
 
55
66
  # Copy over assets
56
67
  copy_assets
57
68
 
58
69
  # Update index.html
59
- layout = File.read('templates/layout.html')
70
+ layout = File.read(dir 'templates/layout.html')
60
71
  layout = Erubis::Eruby.new(layout)
61
72
 
62
- index_compiled = layout.result(config: $config, episodes: episodes) do
63
- index = Erubis::Eruby.new(File.read('templates/index.html'))
64
- index.result(config: $config, episodes: episodes, test: "hello, world") do |episode|
65
- ep = Erubis::Eruby.new(File.read('templates/episode.html'))
66
- ep.result(config: $config, episodes: episodes, episode: episode)
73
+ index_compiled = layout.result(config: @config) do
74
+ index = Erubis::Eruby.new(File.read(dir 'templates/index.html'))
75
+ index.result(config: @config, posts: posts) do |post|
76
+ ep = Erubis::Eruby.new(File.read(dir 'templates/post.html'))
77
+ ep.result(config: @config, posts: posts, post: post)
67
78
  end
68
79
  end
69
80
  write_output_file('index.html') {|f| f.write(index_compiled) }
70
81
 
71
- # Update episode pages
72
- episodes.each do |episode|
73
- layout = File.read('templates/layout.html')
82
+ # Update post pages
83
+ posts.each do |post|
84
+ layout = File.read(dir 'templates/layout.html')
74
85
  layout = Erubis::Eruby.new(layout)
75
- episode_compiled = layout.result(config: $config, episodes: episodes) do
76
- ep = Erubis::Eruby.new(File.read('templates/episode.html'))
77
- ep.result(config: $config, episodes: episodes, episode: episode)
86
+ post_compiled = layout.result(config: @config) do
87
+ ep = Erubis::Eruby.new(File.read(dir 'templates/post.html'))
88
+ ep.result(config: @config, posts: posts, post: post)
78
89
  end
79
- write_output_file(episode.path!) {|f| f.write(episode_compiled) }
90
+ write_output_file(post.path!) {|f| f.write(post_compiled) }
80
91
  end
81
92
 
82
93
  # Copy over iTunes.png
@@ -87,44 +98,24 @@ module Woody
87
98
  end
88
99
 
89
100
  # Update (iTunes) RSS
90
- $config['itunes']['explicit'] = "no" if $config['itunes']['explicit'].nil?
101
+ @config['itunes']['explicit'] = "no" if @config['itunes']['explicit'].nil?
91
102
  feedxml = File.read File.join($source_root, "feed.xml") # Use feed.xml template in gem, not in site's template folder.
92
103
  feed = Erubis::Eruby.new(feedxml)
93
- feed_compiled = feed.result(config: $config, episodes: episodes)
104
+ feed_compiled = feed.result(config: @config, posts: posts)
94
105
  write_output_file("feed.xml") {|f| f.write(feed_compiled) }
95
106
 
96
107
 
97
-
98
- # TODO: Update General RSS
99
-
100
-
101
108
  # Purge left over files
102
109
  purge_output
103
110
 
104
111
  # Remove all empty directories from the output
105
- Dir['output/**/*'].select { |d| File.directory? d }.select { |d| (Dir.entries(d) - %w[ . .. ]).empty? }.each { |d| Dir.rmdir d }
112
+ Dir[dir 'output/**/*'].select { |d| File.directory? d }.select { |d| (Dir.entries(d) - %w[ . .. ]).empty? }.each { |d| Dir.rmdir d }
106
113
  end
107
114
 
108
115
  private
109
116
 
110
- # Safely copies files to the output directory
111
- def self.copy_file_to_output(source, destination)
112
- d = File.join("output", destination)
113
- FileUtils.copy source, d
114
- @@touchedfiles << d
115
- end
116
-
117
- # Safely writes files to the output directory
118
- def self.write_output_file(filename, &block)
119
- file = File.join("output", filename)
120
- File.open(file, 'w') do |f|
121
- yield f
122
- end
123
- @@touchedfiles << file
124
- end
125
-
126
117
  # Prompts for metadata for new media files
127
- def self.prompt_metadata(meta, episodes, filesfound, filename)
118
+ def prompt_metadata(meta, posts, filesfound, filename)
128
119
  puts "Found new media file: #{filename}"
129
120
  if agree("Add metadata for this file? ")
130
121
  m = Hash.new
@@ -136,7 +127,7 @@ module Woody
136
127
  m['explicit'] = agree "Explicit content?: "
137
128
 
138
129
  meta[filename] = m
139
- episodes << Episode.new(filename, m['title'], Date.parse(m['date'].to_s), m['synopsis'], m['subtitle'], m['tags'], m['explicit'])
130
+ posts << Episode.new(self, filename, m['title'], Date.parse(m['date'].to_s), m['synopsis'], m['subtitle'], m['tags'], m['explicit'])
140
131
  filesfound << filename
141
132
 
142
133
  write_meta meta
@@ -146,27 +137,44 @@ module Woody
146
137
  end
147
138
 
148
139
  # Writes the metadata file
149
- def self.write_meta(meta)
150
- File.open( 'content/metadata.yml', 'w' ) do |out|
140
+ def write_meta(meta)
141
+ File.open(dir('content/metadata.yml'), 'w' ) do |out|
151
142
  YAML.dump meta, out
152
143
  end
153
144
  end
154
145
 
146
+ # Safely copies files to the output directory
147
+ def copy_file_to_output(source, destination)
148
+ d = dir(File.join("output", destination))
149
+ FileUtils.copy source, d
150
+ @touchedfiles << undir(d)
151
+ end
152
+
153
+ # Safely writes files to the output directory
154
+ def write_output_file(filename, &block)
155
+ file = dir(File.join("output", filename))
156
+ File.open(file, 'w') do |f|
157
+ yield f
158
+ end
159
+ @touchedfiles << undir(file)
160
+ end
161
+
162
+
155
163
  # Copies custom assets to output
156
- def self.copy_assets
157
- Dir.glob "templates/assets/**/*" do |item|
164
+ def copy_assets
165
+ Dir.glob dir("templates/assets/**/*") do |item|
158
166
  next if File.directory? item
159
- d = item[10..-1] # Cut off "templates/" at beginning
167
+ d = undir item
168
+ d = d[10..-1] # Cut off "templates/" at beginning
160
169
  copy_file_to_output item, d
161
170
  end
162
171
  end
163
172
 
164
-
165
173
  # Deletes old files from the site's output directory
166
- def self.purge_output
167
- Dir.glob "output/**/*" do |item|
174
+ def purge_output
175
+ Dir.glob dir("output/**/*") do |item|
168
176
  next if File.directory? item
169
- File.delete item unless @@touchedfiles.include? item
177
+ File.delete item unless @touchedfiles.include? undir(item)
170
178
  end
171
179
  end
172
180
 
@@ -1,13 +1,13 @@
1
- module Woody
1
+ class Woody
2
2
  # Handles functions relating to deploying the Woody site
3
3
  module Deployer
4
- @@touchedfiles = []
5
4
  # Deploys the Woody site to S3
6
- def self.deploy
5
+ def deploy
7
6
  puts "Deploying..."
8
7
 
9
- Dir.glob "output/**/*" do |item|
8
+ Dir.glob dir("output/**/*") do |item|
10
9
  next if File.directory? item
10
+ item = undir item
11
11
  name = item[7..-1] # Remove "output/"
12
12
  next if name == "index.html" # These *must* be left until last
13
13
  next if name == "feed.xml"
@@ -26,17 +26,17 @@ module Woody
26
26
 
27
27
  # Deletes old objects from the S3 bucket
28
28
  # @param [Array] touchedfiles specifies the S3 objects to keep
29
- def self.purge_bucket
30
- bucket = AWS::S3::Bucket.find $bucketname
31
- prefix = $config['s3']['prefix']
29
+ def purge_bucket
30
+ bucket = AWS::S3::Bucket.find @bucketname
31
+ prefix = @config['s3']['prefix']
32
32
  if prefix.nil?
33
33
  bucket.objects.each do |object|
34
- object.delete unless @@touchedfiles.include? object.key
34
+ object.delete unless @s3touchedobjects.include? object.key
35
35
  end
36
36
  else
37
37
  bucket.objects.each do |object|
38
38
  if object.key.start_with? prefix # If using a prefix, don't delete anything outside of that 'subdirectory'
39
- object.delete unless @@touchedfiles.include? object.key
39
+ object.delete unless @s3touchedobjects.include? object.key
40
40
  end
41
41
  end
42
42
  end
@@ -49,18 +49,20 @@ module Woody
49
49
  # Prints notices to STDOUT
50
50
  # @param [String] objectname specifies the S3 object's key/name
51
51
  # @param [String] filepath specifies the path to the file to upload
52
- def self.upload(objectname, filepath)
53
- prefix = $config['s3']['prefix']
52
+ def upload(objectname, filepath)
53
+ prefix = @config['s3']['prefix']
54
54
  unless prefix.nil?
55
55
  objectname = File.join(prefix, objectname)
56
56
  end
57
57
 
58
+ filepath = dir(filepath)
59
+
58
60
  # Generate hash of file
59
61
  hash = filehash filepath
60
- @@touchedfiles << objectname
62
+ @s3touchedobjects << objectname
61
63
  # Get hash of version already uploaded, if available.
62
64
  begin
63
- object = AWS::S3::S3Object.find objectname, $bucketname
65
+ object = AWS::S3::S3Object.find objectname, @bucketname
64
66
  oldhash = object.metadata['hash']
65
67
  rescue AWS::S3::NoSuchKey
66
68
  # File not uploaded yet
@@ -69,7 +71,7 @@ module Woody
69
71
  unless hash == oldhash
70
72
  # Don't reupload if file hasn't changed
71
73
  puts "#{objectname}: Uploading"
72
- AWS::S3::S3Object.store(objectname, open(filepath), $bucketname, access: :public_read, 'x-amz-meta-hash' => hash)
74
+ AWS::S3::S3Object.store(objectname, open(filepath), @bucketname, access: :public_read, 'x-amz-meta-hash' => hash)
73
75
  else
74
76
  puts "#{objectname}: Not uploading, hasn't changed since last time."
75
77
  end
@@ -80,7 +82,7 @@ module Woody
80
82
  # Stored in S3 object metadata (x-amz-meta-hash) and used to avoid re-uploading unchanged files
81
83
  # @param [String] filepath path to file
82
84
  # @return [String] hash of file
83
- def self.filehash(filepath)
85
+ def filehash(filepath)
84
86
  sha1 = Digest::SHA1.new
85
87
  File.open(filepath) do|file|
86
88
  buffer = ''
data/lib/woody/episode.rb CHANGED
@@ -1,57 +1,36 @@
1
- module Woody
2
- # Represents an episode of the podcast
3
- class Episode
1
+ require "woody/post"
2
+
3
+ class Woody
4
+ # Represents an episode of the podcast. Inherits from Post.
5
+ class Episode < Post
4
6
  # Creates a new Episode object from segment of metadata.yml
5
7
  # @param [String] filename specifies the name of the MP3 file
6
8
  # @param [Hash] meta is the relevant part of metadata.yml
7
9
  # @return [Episode] the new Episode object
8
- def self.new_from_meta(filename, meta)
9
- return Episode.new(filename, meta['title'], Date.parse(meta['date'].to_s), meta['synopsis'], meta['subtitle'], meta['tags'], meta['explicit'])
10
+ def self.new_from_meta(site, filename, meta)
11
+ return Episode.new(site, filename, meta['title'], Date.parse(meta['date'].to_s), meta['synopsis'], meta['subtitle'], meta['tags'], meta['explicit'])
10
12
  end
11
13
 
12
14
  # Creates a new Episode object
13
15
  # @param [String] filename specifies the name of the MP3 file
14
16
  # @param [String] title specifies the episode's title
15
17
  # @param [Date] date specifies the episode's published date
16
- # @param [String] synopsis specifies the episode's synopsis
18
+ # @param [String] body specifies the episode's synopsis/body
17
19
  # @param [String] subtitle specifies the episode's subtitle
18
20
  # @param [Array] tags specifies the episode's tags - each element is a String
19
21
  # @return [Episode] the new Episode object
20
- def initialize(filename, title, date, synopsis, subtitle = nil, tags = [], explicit = false)
21
- @filename = filename
22
- @title = title
23
- @date = date
24
- @synopsis = synopsis
25
- @subtitle = subtitle
26
- @tags = tags
22
+ def initialize(site, filename, title, date, raw_body, subtitle = nil, tags = [], explicit = false)
23
+ super site, filename, title, subtitle, raw_body, date, tags
27
24
  @explicit = explicit
28
- @compiledname = @filename.gsub(/[^0-9A-Za-z .]/, '').gsub(' ', '_')
25
+ @compiledname = @filename.gsub(/[^0-9A-Za-z ._]/, '').gsub(' ', '_')
29
26
  end
30
27
 
31
- attr_accessor :filename, :title, :date, :synopsis, :tags, :subtitle, :explicit, :compiledname
32
-
33
- # @return the episode's page URL where possible, otherwise false
34
- def url
35
- return "#{$config['urlbase']}#{path!}" unless path! == false
36
- return false
37
- end
28
+ attr_accessor :explicit
38
29
 
39
- # @return the episode's page path! where possible, otherwise false. Does not take prefix in to account.
40
- def path!(leader=true)
41
- return "#{leader ? "/" : ""}episode/#{@compiledname[0..-5]}.html" unless @compiledname.nil?
42
- return false
43
- end
44
-
45
- # @return the episode's page path! where possible, otherwise false. Includes the site prefix if enabled.
46
- def path(leader=true)
47
- prefix = $config['s3']['prefix']
48
- return "#{leader ? "/" : ""}#{prefix.nil? ? "" : prefix + "/" }episode/#{@compiledname[0..-5]}.html" unless @compiledname.nil?
49
- return false
50
- end
51
30
 
52
31
  # @return the episode's media file URL where possible, otherwise false
53
32
  def file_url
54
- return "#{$config['urlbase']}#{file_path!}" unless file_path! == false
33
+ return "#{@site.config['urlbase']}#{file_path!}" unless file_path! == false
55
34
  return false
56
35
  end
57
36
 
@@ -63,23 +42,19 @@ module Woody
63
42
 
64
43
  # @return the episode's media file path! where possible, otherwise false. Includes site prefix if enabled.
65
44
  def file_path(leader=true)
66
- prefix = $config['s3']['prefix']
45
+ prefix = @site.config['s3']['prefix']
67
46
  return "#{leader ? "/" : ""}#{prefix.nil? ? "" : prefix + "/" }assets/mp3/#{@compiledname}" unless @compiledname.nil?
68
47
  return false
69
48
  end
70
49
 
71
50
 
72
- # @return [String] a comma separated list of tags, or nil if no tags
73
- def keywords
74
- @tags.join ', ' unless @tags.nil? or @tags.empty?
75
- end
76
51
 
77
52
  # @return [Integer] the size of the episodes media file in bytes
78
53
  def size
79
- File.size File.join("content", filename)
54
+ File.size @site.dir(File.join("content", filename))
80
55
  end
81
56
 
82
- # @return [String] 'yes' if explicit content, otherwise n'o'
57
+ # @return [String] 'yes' if explicit content, otherwise 'no'
83
58
  def explicit_string
84
59
  @explicit ? 'yes' : 'no'
85
60
  end
@@ -88,7 +63,7 @@ module Woody
88
63
  def duration
89
64
  return @duration unless @duration.nil?
90
65
  length = 0
91
- Mp3Info.open(File.join("content", filename)) do |mp3|
66
+ Mp3Info.open(@site.dir(File.join("content", filename))) do |mp3|
92
67
  length = mp3.length
93
68
  end
94
69
  @duration = Time.at(length).gmtime.strftime('%R:%S') # Should work up to 24 hours
@@ -97,8 +72,9 @@ module Woody
97
72
  end
98
73
  end
99
74
 
100
- def <=> (other)
101
- other.date <=> self.date
75
+
76
+ def has_file?
77
+ true
102
78
  end
103
79
 
104
80
  end
@@ -1,4 +1,4 @@
1
- module Woody
1
+ class Woody
2
2
  # Handles functions related to generating Woody sites and updating them and their data stores
3
3
  module Generator
4
4
  # Generates a blank skeleton Woody site
@@ -17,7 +17,7 @@ module Woody
17
17
  cdir_p("#{name}/templates")
18
18
  cpy_t("layout.html", "#{name}/templates/layout.html")
19
19
  cpy_t("index.html", "#{name}/templates/index.html")
20
- cpy_t("episode.html", "#{name}/templates/episode.html")
20
+ cpy_t("post.html", "#{name}/templates/post.html")
21
21
 
22
22
  cdir_p("#{name}/templates/assets")
23
23
  cpy_t("stylesheet.css", "#{name}/templates/assets/stylesheet.css")
@@ -25,23 +25,24 @@ module Woody
25
25
  cdir_p("#{name}/content")
26
26
  cpy_t("metadata.yml", "#{name}/content/metadata.yml")
27
27
  cpy_t("iTunes.png", "#{name}/content/iTunes.png")
28
+ cdir_p("#{name}/content/posts")
28
29
 
29
30
  cdir_p("#{name}/output")
30
31
  cdir_p("#{name}/output/assets")
31
32
  cdir_p("#{name}/output/assets/mp3")
32
- cdir_p("#{name}/output/episode")
33
+ cdir_p("#{name}/output/post")
33
34
 
34
35
  puts "Done!"
35
36
  puts "Now, do `cd #{name}` then edit the config file, woody-config.yml."
36
37
  end
37
38
 
38
39
  # Replaces the templates in the Woody site with the gem's current default ones
39
- def self.update_templates
40
+ def self.update_templates(site)
40
41
  puts "Updating templates..."
41
- cpy_t("layout.html", "templates/layout.html")
42
- cpy_t("index.html", "templates/index.html")
43
- cpy_t("episode.html", "templates/episode.html")
44
- cpy_t("stylesheet.css", "templates/assets/stylesheet.css")
42
+ cpy_t("layout.html", site.dir("templates/layout.html"))
43
+ cpy_t("index.html", site.dir("templates/index.html"))
44
+ cpy_t("post.html", site.dir("templates/post.html"))
45
+ cpy_t("stylesheet.css", site.dir("templates/assets/stylesheet.css"))
45
46
  puts "Done! Thanks for updating :)"
46
47
  end
47
48
 
data/lib/woody/post.rb ADDED
@@ -0,0 +1,63 @@
1
+ require 'kramdown'
2
+
3
+ class Woody
4
+ # Represents a post
5
+ class Post
6
+ # Creates a new Post object
7
+ # @param [String] filename specifies the name of the post file
8
+ # @param [String] title specifies the Post's title
9
+ # @param [String] subtitle specifies the Post's subtitle
10
+ # @param [String] body specifies the Post's body
11
+ # @param [Date] date specifies the Post's published date
12
+ # @param [Array] tags specifies the Post's tags - each element is a String
13
+ # @return [Post] the new Post object
14
+ def initialize(site, filename, title, subtitle, raw_body, date, tags = [], compiledname = nil)
15
+ @site = site
16
+ @filename = filename
17
+ @title = title
18
+ @subtitle = subtitle
19
+ @raw_body = raw_body
20
+ @date = date
21
+ @tags = tags.nil? ? [] : tags
22
+ @compiledname = @filename[6..-1].gsub(/[^0-9A-Za-z ._]/, '').gsub(' ', '_')
23
+ end
24
+ attr_accessor :filename, :title, :subtitle, :raw_body, :date, :tags, :compiledname
25
+
26
+ def body(regenerate = false)
27
+ return @body unless @body.nil? or regenerate
28
+ return @body = Kramdown::Document.new(@raw_body).to_html
29
+ end
30
+
31
+ # @return the Page's page URL where possible, otherwise false
32
+ def url
33
+ return "#{@site.config['urlbase']}#{path!}" unless path! == false
34
+ return false
35
+ end
36
+
37
+ # @return the Page's page path where possible, otherwise false. Does not take prefix in to account.
38
+ def path!(leader=true)
39
+ return "#{leader ? "/" : ""}post/#{@compiledname.chomp(File.extname(@compiledname))}.html" unless @compiledname.nil?
40
+ return false
41
+ end
42
+
43
+ # @return the Page's page path where possible, otherwise false. Includes the site prefix if enabled.
44
+ def path(leader=true)
45
+ prefix = @site.config['s3']['prefix']
46
+ return "#{leader ? "/" : ""}#{prefix.nil? ? "" : prefix + "/" }post/#{@compiledname.chomp(File.extname(@compiledname))}.html" unless @compiledname.nil?
47
+ return false
48
+ end
49
+
50
+ # @return [String] a comma separated list of tags, or nil if no tags
51
+ def keywords
52
+ @tags.join ', ' unless @tags.nil? or @tags.empty?
53
+ end
54
+
55
+ def has_file?
56
+ false
57
+ end
58
+
59
+ def <=> (other)
60
+ other.date <=> self.date
61
+ end
62
+ end
63
+ end
data/lib/woody/version.rb CHANGED
@@ -1,4 +1,4 @@
1
- module Woody
1
+ class Woody
2
2
  # Specifies Woody gem version
3
- VERSION = "0.3.4"
3
+ VERSION = "0.4.0"
4
4
  end
data/lib/woody.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require "woody/version"
2
+ require "woody/post"
2
3
  require "woody/episode"
3
4
  require "woody/compiler"
4
5
  require "woody/deployer"
@@ -19,34 +20,45 @@ require 'mp3info'
19
20
  $VERBOSE = oldverbosity
20
21
 
21
22
  # Woody podcast static site generator
22
- module Woody
23
+ class Woody
24
+ include Generator
25
+ include Compiler
26
+ include Deployer
27
+
28
+
23
29
  # Path of template directory inside gem
24
30
  $source_root = File.expand_path("../../templates", __FILE__)
25
31
 
26
32
  # Load configuration and connect to S3
27
- def self.init
33
+ def initialize(directory = ".")
34
+ @directory = directory
35
+ @touchedfiles = []
36
+ @s3touchedobjects = []
37
+
38
+
39
+
28
40
  begin
29
- $config = YAML.load_file("woody-config.yml")
41
+ @config = YAML.load_file(dir("woody-config.yml"))
30
42
  rescue Errno::ENOENT
31
43
  puts "This doesn't look like a valid Woody site directory!"
32
44
  exit!
33
45
  end
34
46
 
35
47
  # Strip trailing slash from urlbase, if present.
36
- if $config['urlbase'].end_with? "/"
37
- $config['urlbase'] = $config['urlbase'][0..-2]
48
+ if @config['urlbase'].end_with? "/"
49
+ @config['urlbase'] = @config['urlbase'][0..-2]
38
50
  end
39
51
 
40
- if $config['distributiontype'] == "s3"
41
- prefix = $config['s3']['prefix']
52
+ if @config['distributiontype'] == "s3"
53
+ prefix = @config['s3']['prefix']
42
54
  unless prefix.nil?
43
- $config['urlbase'] = $config['urlbase'] + "/" + prefix
55
+ @config['urlbase'] = @config['urlbase'] + "/" + prefix
44
56
  end
45
57
  end
46
58
 
47
- options = {
48
- :access_key_id => $config['s3']['accesskey']['id'],
49
- :secret_access_key => $config['s3']['accesskey']['secret']
59
+ s3options = {
60
+ :access_key_id => @config['s3']['accesskey']['id'],
61
+ :secret_access_key => @config['s3']['accesskey']['secret']
50
62
  }
51
63
 
52
64
  unless ENV['http_proxy'].nil?
@@ -56,14 +68,28 @@ module Woody
56
68
  p[:port] = uri.port
57
69
  p[:user] = uri.user unless uri.user.nil?
58
70
  p[:password] = uri.password unless uri.password.nil?
59
- options[:proxy] = p
71
+ s3options[:proxy] = p
60
72
  end
61
73
 
62
- AWS::S3::Base.establish_connection!(options)
63
- AWS::S3::DEFAULT_HOST.replace $config['s3']['hostname']
64
- $bucketname = $config['s3']['bucket']
74
+ AWS::S3::Base.establish_connection!(s3options)
75
+ AWS::S3::DEFAULT_HOST.replace @config['s3']['hostname']
76
+ @bucketname = @config['s3']['bucket']
65
77
  end
66
78
 
79
+ attr_accessor :config
80
+ attr_reader :directory
81
+
82
+ def dir(dir="")
83
+ File.expand_path(File.join(@directory, dir))
84
+ end
85
+
86
+ def undir(string)
87
+ string[dir.length+1..-1]
88
+ end
89
+
90
+ def update_templates
91
+ Generator::update_templates(self)
92
+ end
67
93
  end
68
94
 
69
95
 
data/templates/feed.xml CHANGED
@@ -17,27 +17,28 @@
17
17
  <itunes:email><%= config['itunes']['owner']['email'] %></itunes:email>
18
18
  </itunes:owner>
19
19
 
20
- <itunes:image href="<%= $config['urlbase'] + "/assets/iTunes.png" %>"/>
21
- <itunes:category text="<%= $config['itunes']['category'] %>"/>
20
+ <itunes:image href="<%= config['urlbase'] + "/assets/iTunes.png" %>"/>
21
+ <itunes:category text="<%= config['itunes']['category'] %>"/>
22
22
 
23
- <atom:link href="<%= $config['urlbase'] %>/feed.xml" rel="self" type="application/rss+xml" />
23
+ <atom:link href="<%= config['urlbase'] %>/feed.xml" rel="self" type="application/rss+xml" />
24
24
 
25
25
 
26
- <%- episodes.each do |episode| %>
26
+ <%- posts.each do |post| %>
27
+ <%- next unless post.has_file? %>
27
28
  <item>
28
- <title><%= episode.title %></title>
29
- <itunes:subtitle><%= episode.subtitle %></itunes:subtitle>
30
- <itunes:summary><%= episode.synopsis %></itunes:summary>
31
- <pubDate><%= episode.date.rfc2822 %></pubDate>
32
- <itunes:duration><%= episode.duration %></itunes:duration>
33
- <itunes:keywords><%= episode.keywords %></itunes:keywords>
34
- <itunes:explicit><%= episode.explicit_string %></itunes:explicit>
35
- <description><%= episode.synopsis %></description>
36
- <enclosure url="<%= episode.file_url %>" length="<%= episode.size %>" type="audio/mpeg"/>
37
- <guid><%= episode.url %></guid>
29
+ <title><%= post.title %></title>
30
+ <itunes:subtitle><%= post.subtitle %></itunes:subtitle>
31
+ <itunes:summary><%= post.body %></itunes:summary>
32
+ <pubDate><%= post.date.rfc2822 %></pubDate>
33
+ <itunes:duration><%= post.duration %></itunes:duration>
34
+ <itunes:keywords><%= post.keywords %></itunes:keywords>
35
+ <itunes:explicit><%= post.explicit_string %></itunes:explicit>
36
+ <description><%= post.body %></description>
37
+ <enclosure url="<%= post.file_url %>" length="<%= post.size %>" type="audio/mpeg"/>
38
+ <guid><%= post.url %></guid>
38
39
  <category>Podcasts</category>
39
40
  </item>
40
- <% end %>
41
+ <% end %>
41
42
 
42
43
  </channel>
43
44
  </rss>
data/templates/index.html CHANGED
@@ -1,7 +1,7 @@
1
1
  <h2>Episodes:</h2>
2
- <%= link_to "RSS Feed", "#{$config['urlbase']}/feed.xml" %>
3
- <% episodes.each do |episode| %>
2
+ <%= link_to "RSS Feed", "#{ config['urlbase'] }/feed.xml" %>
3
+ <% posts.each do |post| %>
4
4
  <div class="episode">
5
- <%= yield episode %>
5
+ <%= yield post %>
6
6
  </div>
7
7
  <% end %>
@@ -1,13 +1,14 @@
1
1
  <!DOCTYPE html>
2
2
  <html>
3
3
  <head>
4
- <title><%= $config['title'] %></title>
4
+ <meta charset="UTF-8" />
5
+ <title><%= config['title'] %></title>
5
6
  <%= generator_meta_tag %>
6
7
  <link rel="stylesheet" type="text/css" href="/assets/stylesheet.css" />
7
8
  </head>
8
9
  <body>
9
- <h1><%= link_to $config['title'], $config['urlbase'] %></h1>
10
- <h2><%= $config['subtitle'] %></h2>
10
+ <h1><%= link_to config['title'], config['urlbase'] %></h1>
11
+ <h2><%= config['subtitle'] %></h2>
11
12
  <hr />
12
13
  <%= yield %>
13
14
  </body>
@@ -0,0 +1,19 @@
1
+ <h3><%= link_to post.title, post.path %></h3>
2
+ <h4><%= post.subtitle %></h4>
3
+
4
+ <%- if post.has_file? %>
5
+ Player goes here
6
+
7
+ <a href="<%= post.file_path %>">Download MP3</a>
8
+ <% end %>
9
+
10
+ <div class="synopsis body">
11
+ <%= post.body %>
12
+ </div>
13
+
14
+ <div class="tags">
15
+ <strong>Tags:</strong>
16
+ <% post.tags.each do |tag| %>
17
+ <span class="tag"><%= tag %> </span>
18
+ <% end %>
19
+ </div>
data/woody.gemspec CHANGED
@@ -22,6 +22,8 @@ Gem::Specification.new do |gem|
22
22
  gem.add_runtime_dependency 'aws-s3'
23
23
  gem.add_runtime_dependency 'commander'
24
24
  gem.add_runtime_dependency 'highline'
25
+ gem.add_runtime_dependency 'preamble'
26
+ gem.add_runtime_dependency 'kramdown'
25
27
 
26
28
  # 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."
27
29
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: woody
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.4
4
+ version: 0.4.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-12 00:00:00.000000000 Z
12
+ date: 2012-12-15 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: erubis
@@ -91,6 +91,38 @@ dependencies:
91
91
  - - ! '>='
92
92
  - !ruby/object:Gem::Version
93
93
  version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: preamble
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :runtime
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: kramdown
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
94
126
  description: Woody
95
127
  email:
96
128
  - david@davidr.me
@@ -110,13 +142,14 @@ files:
110
142
  - lib/woody/deployer.rb
111
143
  - lib/woody/episode.rb
112
144
  - lib/woody/generator.rb
145
+ - lib/woody/post.rb
113
146
  - lib/woody/version.rb
114
- - templates/episode.html
115
147
  - templates/feed.xml
116
148
  - templates/iTunes.png
117
149
  - templates/index.html
118
150
  - templates/layout.html
119
151
  - templates/metadata.yml
152
+ - templates/post.html
120
153
  - templates/stylesheet.css
121
154
  - templates/woody-config.yml
122
155
  - woody.gemspec
@@ -1,16 +0,0 @@
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>