woody 0.3.4 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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>