henshin 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/.gitignore +1 -1
  2. data/README.markdown +0 -1
  3. data/Rakefile +4 -1
  4. data/VERSION +1 -1
  5. data/bin/files.rb +46 -0
  6. data/bin/henshin +47 -79
  7. data/henshin.gemspec +37 -14
  8. data/lib/henshin.rb +50 -36
  9. data/lib/henshin/archive.rb +161 -0
  10. data/lib/henshin/categories.rb +6 -1
  11. data/lib/henshin/ext.rb +2 -53
  12. data/lib/henshin/gen.rb +16 -15
  13. data/lib/henshin/plugin.rb +20 -7
  14. data/lib/henshin/plugins/highlight.rb +31 -0
  15. data/lib/henshin/plugins/liquid.rb +48 -14
  16. data/lib/henshin/plugins/maruku.rb +3 -4
  17. data/lib/henshin/plugins/sass.rb +7 -6
  18. data/lib/henshin/plugins/textile.rb +3 -4
  19. data/lib/henshin/post.rb +50 -8
  20. data/lib/henshin/site.rb +60 -34
  21. data/lib/henshin/tags.rb +5 -1
  22. data/test/site/css/{print.sass → includes/reset.sass} +0 -3
  23. data/test/site/css/{screen.css → print.css} +1 -4
  24. data/test/site/css/screen.sass +70 -0
  25. data/test/site/includes/head.html +1 -0
  26. data/test/site/index.html +12 -2
  27. data/test/site/layouts/archive_date.html +19 -0
  28. data/test/site/layouts/archive_month.html +19 -0
  29. data/test/site/layouts/archive_year.html +19 -0
  30. data/test/site/layouts/category_index.html +5 -4
  31. data/test/site/layouts/category_page.html +2 -2
  32. data/test/site/layouts/main.html +1 -36
  33. data/test/site/layouts/post.html +15 -5
  34. data/test/site/layouts/tag_index.html +3 -3
  35. data/test/site/layouts/tag_page.html +2 -2
  36. data/test/site/options.yaml +7 -4
  37. data/test/site/posts/Testing-Stuff.markdown +7 -1
  38. data/test/test_archives.rb +27 -0
  39. data/test/test_categories.rb +0 -0
  40. data/test/test_gens.rb +28 -7
  41. data/test/test_options.rb +4 -2
  42. data/test/test_posts.rb +50 -14
  43. data/test/test_site.rb +55 -7
  44. data/test/test_statics.rb +0 -0
  45. data/test/test_tags.rb +0 -0
  46. data/test/text_exts.rb +0 -0
  47. metadata +86 -17
  48. data/lib/henshin/plugins/pygments.rb +0 -17
@@ -3,14 +3,13 @@ require 'maruku'
3
3
 
4
4
  class MarukuPlugin < Henshin::Generator
5
5
 
6
- attr_accessor :extensions, :config
7
-
8
- Defaults = {}
6
+ attr_accessor :extensions, :config, :priority
9
7
 
10
8
  def initialize( override={} )
11
9
  @extensions = {:input => ['markdown', 'mkdwn', 'md'],
12
10
  :output => 'html'}
13
- @config = Defaults.merge(override)
11
+ @config = {}
12
+ @priority = 5
14
13
  end
15
14
 
16
15
  def generate( content )
@@ -3,7 +3,7 @@ require 'sass'
3
3
 
4
4
  class SassPlugin < Henshin::Generator
5
5
 
6
- attr_accessor :extensions, :config, :opts_name
6
+ attr_accessor :extensions, :config, :priority
7
7
 
8
8
  Defaults = {:ignore_layouts => true,
9
9
  :style => :nested}
@@ -11,17 +11,18 @@ class SassPlugin < Henshin::Generator
11
11
  def initialize
12
12
  @extensions = {:input => ['sass', 'scss'],
13
13
  :output => 'css'}
14
- @opts_name = :sass
14
+ @config = {:ignore_layouts => true,
15
+ :style => :nested}
16
+ @priority = 5
15
17
  end
16
18
 
17
19
  def configure( override )
18
- override ? @config = Defaults.merge(override) : @config = Defaults
20
+ @config.merge!(override) if override
19
21
  end
20
22
 
21
23
  def generate( content )
22
- engine = Sass::Engine.new(content, config)
23
- output = engine.render
24
+ Sass::Engine.new(content, @config).render
24
25
  end
25
26
 
26
- Henshin.register! self
27
+ Henshin.register! self, :sass
27
28
  end
@@ -3,14 +3,13 @@ require 'redcloth'
3
3
 
4
4
  class TextilePlugin < Henshin::Generator
5
5
 
6
- attr_accessor :extensions, :config
7
-
8
- Defaults = {}
6
+ attr_accessor :extensions, :config, :priority
9
7
 
10
8
  def initialize( override={} )
11
9
  @extensions = {:input => ['textile'],
12
10
  :output => 'html'}
13
- @config = Defaults.merge(override)
11
+ @config = {}
12
+ @priority = 5
14
13
  end
15
14
 
16
15
  def generate( content )
@@ -60,9 +60,9 @@ module Henshin
60
60
  file_data.each_with_index do |data, i|
61
61
  if data_order[i].include? 'title'
62
62
  if data_order[i].include? 'dashes'
63
- override[:title] = data.gsub(/-/, ' ').titlize
63
+ override[:title] = data.gsub(/-/, ' ')
64
64
  else
65
- override[:title] = data.titlize
65
+ override[:title] = data
66
66
  end
67
67
  elsif data_order[i].include? 'date'
68
68
  override[:date] = data
@@ -92,7 +92,7 @@ module Henshin
92
92
  #
93
93
  # @param [Hash] override data to override settings with
94
94
  def override( override )
95
- @title = override[:title] if override[:title]
95
+ @title = override[:title].titlecase if override[:title]
96
96
  @layout = @site.layouts[ override[:layout] ] if override[:layout]
97
97
  @date = Time.parse( override[:date] ) if override[:date]
98
98
  @tags = override[:tags].split(', ') if override[:tags]
@@ -112,17 +112,24 @@ module Henshin
112
112
  #
113
113
  # @return [Hash] the payload for the layout engine
114
114
  def payload
115
- {
115
+ r = {
116
116
  'yield' => @content,
117
117
  'site' => @site.payload['site'],
118
118
  'post' => self.to_hash
119
119
  }
120
+ r['post']['next'] = self.next.to_hash if self.next
121
+ r['post']['prev'] = self.prev.to_hash if self.prev
122
+ r
120
123
  end
121
124
 
122
125
  # Turns all of the post data into a hash
123
126
  #
124
127
  # @return [Hash]
125
128
  def to_hash
129
+ tags = []
130
+ @site.tags.select{ |t| @tags.include?(t) }.each do |k, tag|
131
+ tags << {'name' => tag.name, 'url' => tag.url}
132
+ end
126
133
  {
127
134
  'title' => @title,
128
135
  'author' => @author,
@@ -130,18 +137,44 @@ module Henshin
130
137
  'url' => self.url,
131
138
  'date' => @date,
132
139
  'category' => @category,
133
- 'tags' => @tags,
134
- 'content' => @content
140
+ 'tags' => tags,
141
+ 'content' => @content
135
142
  }
136
143
  end
144
+
145
+ # Gets the post after this one
146
+ #
147
+ # @return [Post] next post
148
+ def next
149
+ if i = @site.posts.index(self)
150
+ if i < @site.posts.size - 1
151
+ @site.posts[i+1]
152
+ else
153
+ nil
154
+ end
155
+ end
156
+ end
157
+
158
+ # Gets the post before this one
159
+ #
160
+ # @return [Post] previous post
161
+ def prev
162
+ if i = @site.posts.index(self)
163
+ if i > 0
164
+ @site.posts[i-1]
165
+ else
166
+ nil
167
+ end
168
+ end
169
+ end
137
170
 
138
171
 
139
172
  ##
140
173
  # Writes the file to the correct place
141
174
  def write
142
175
  write_path = File.join( config[:root], config[:target], permalink )
143
- FileUtils.mkdir_p File.join( write_path.directory )
144
- file = File.new( File.join( write_path ), "w" )
176
+ FileUtils.mkdir_p write_path.directory
177
+ file = File.new( write_path, "w" )
145
178
  file.puts( @content )
146
179
  end
147
180
 
@@ -158,6 +191,15 @@ module Henshin
158
191
  end
159
192
  end
160
193
 
194
+ def <=>(other)
195
+ s = self.date <=> other.date
196
+ if s == 0
197
+ self.permalink <=> other.permalink
198
+ else
199
+ s
200
+ end
201
+ end
202
+
161
203
  def inspect
162
204
  "#<Post:#{@path}>"
163
205
  end
@@ -16,7 +16,7 @@ module Henshin
16
16
  @gens = []
17
17
  @statics = []
18
18
 
19
- @archive = {}
19
+ @archive = Archive.new( self )
20
20
  @tags = Hash.new { |h, k| h[k] = Tag.new(k) }
21
21
  @categories = Hash.new { |h, k| h[k] = Category.new(k) }
22
22
 
@@ -40,45 +40,43 @@ module Henshin
40
40
  def read
41
41
  self.read_layouts
42
42
  self.read_posts
43
- self.read_others
43
+ self.read_gens
44
+ self.read_statics
44
45
  end
45
46
 
46
47
  # Adds all items in 'layouts' to the layouts array
47
48
  def read_layouts
48
- path = File.join(config[:root], 'layouts')
49
+ path = File.join(@config[:root], 'layouts')
49
50
  Dir.glob(path + '/*.*').each do |layout|
50
51
  layout =~ /([a-zA-Z0-9 _-]+)\.([a-zA-Z0-9-]+)/
51
- @layouts[$1] = layout
52
+ @layouts[$1] = File.open(layout, 'r') {|f| f.read}
52
53
  end
53
54
  end
54
55
 
55
56
  # Adds all items in 'posts' to the posts array
56
57
  def read_posts
57
- path = File.join(config[:root], 'posts')
58
+ path = File.join(@config[:root], 'posts')
58
59
  Dir.glob(path + '/**/*.*').each do |post|
59
60
  @posts << Post.new(post, self)
60
61
  end
61
62
  end
62
63
 
63
- # Gets all other items, and determines whether it's static or needs to be converted
64
- def read_others
65
- path = File.join(config[:root], '**', '*.*')
66
- items = Dir.glob(path)
67
-
68
- ['/_site', '/plugins'].each do |r|
69
- items = items.select {|i| !i.include?( File.join(config[:root], r) )}
70
- end
71
-
72
- gens = items.select {|i| i.gen?(self.config)}
64
+ # Adds all files that need to be run through a plugin in an array
65
+ def read_gens
66
+ files = Dir.glob( File.join(@config[:root], '**', '*.*') )
67
+ gens = files.select {|i| gen?(i) }
73
68
  gens.each do |g|
74
69
  @gens << Gen.new(g, self)
75
70
  end
76
-
77
- static = items.select {|i| i.static?(self.config)}
71
+ end
72
+
73
+ # Adds all static files to an array
74
+ def read_statics
75
+ files = Dir.glob( File.join(@config[:root], '**', '*.*') )
76
+ static = files.select {|i| static?(i) }
78
77
  static.each do |s|
79
78
  @statics << Static.new(s, self)
80
79
  end
81
-
82
80
  end
83
81
 
84
82
 
@@ -103,11 +101,11 @@ module Henshin
103
101
  'description' => @config[:description],
104
102
  'time_zone' => @config[:time_zone],
105
103
  'created_at' => Time.now,
106
- 'posts' => @posts.collect {|i| i.to_hash},
104
+ 'posts' => @posts.collect{|i| i.to_hash},
107
105
  'tags' => @tags.collect {|k, t| t.to_hash},
108
106
  'categories' => @categories.collect {|k, t| t.to_hash},
109
- 'archive' => @archive
110
- }
107
+ 'archive' => @archive.to_hash
108
+ }
111
109
  }
112
110
  end
113
111
 
@@ -129,21 +127,14 @@ module Henshin
129
127
 
130
128
  # @return [Hash] archive hash
131
129
  def build_archive
132
- {
133
- '2010' => {
134
- '01' => [
135
- {'post' => 'hash'},
136
- {'post' => 'hash'}
137
- ]
138
- }
139
- }
130
+ @posts.each {|p| @archive.add_post(p)}
140
131
  end
141
132
 
142
133
  ##
143
134
  # Renders the files
144
135
  def render
145
136
  @posts.each_parallel {|p| p.render}
146
- @gens.each_parallel {|g| g.render}
137
+ @gens.each {|g| g.render}
147
138
  end
148
139
 
149
140
 
@@ -154,6 +145,7 @@ module Henshin
154
145
  @gens.each_parallel {|g| g.write}
155
146
  @statics.each_parallel {|s| s.write}
156
147
 
148
+ @archive.write
157
149
  self.write_tags
158
150
  self.write_categories
159
151
  end
@@ -161,7 +153,7 @@ module Henshin
161
153
  # Writes the necessary pages for tags, but only if the correct layouts are present
162
154
  def write_tags
163
155
  if @layouts['tag_index']
164
- write_path = File.join( config[:root], 'tags', 'index.html' )
156
+ write_path = File.join( @config[:root], 'tags', 'index.html' )
165
157
 
166
158
  tag_index = Gen.new(write_path, self)
167
159
  tag_index.layout = @layouts['tag_index']
@@ -172,7 +164,7 @@ module Henshin
172
164
 
173
165
  if @layouts['tag_page']
174
166
  @tags.each do |n, tag|
175
- write_path = File.join( config[:root], 'tags', tag.name, 'index.html' )
167
+ write_path = File.join( @config[:root], 'tags', tag.name, 'index.html' )
176
168
 
177
169
  payload = {:name => 'tag', :payload => tag.to_hash}
178
170
  tag_page = Gen.new(write_path, self, payload)
@@ -187,7 +179,7 @@ module Henshin
187
179
  # Writes the necessary pages for categories, but only if the correct layouts are present
188
180
  def write_categories
189
181
  if @layouts['category_index']
190
- write_path = File.join( config[:root], 'categories', 'index.html' )
182
+ write_path = File.join( @config[:root], 'categories', 'index.html' )
191
183
 
192
184
  category_index = Gen.new(write_path, self)
193
185
  category_index.layout = @layouts['category_index']
@@ -198,7 +190,7 @@ module Henshin
198
190
 
199
191
  if @layouts['category_page']
200
192
  @categories.each do |n, category|
201
- write_path = File.join( config[:root], 'categories', category.name, 'index.html' )
193
+ write_path = File.join( @config[:root], 'categories', category.name, 'index.html' )
202
194
 
203
195
  payload = {:name => 'category', :payload => category.to_hash}
204
196
  category_page = Gen.new(write_path, self, payload)
@@ -209,6 +201,40 @@ module Henshin
209
201
  end
210
202
  end
211
203
  end
204
+
205
+
206
+ # @return [Bool]
207
+ def static?( path )
208
+ !( layout?(path) || post?(path) || gen?(path) || ignored?(path) )
209
+ end
210
+
211
+ # @return [Bool]
212
+ def layout?( path )
213
+ path.include?('layouts/') && !ignored?(path)
214
+ end
215
+
216
+ # @return [Bool]
217
+ def post?( path )
218
+ path.include?('posts/') && !ignored?(path)
219
+ end
220
+
221
+ # @return [Bool]
222
+ def gen?( path )
223
+ return false if post?(path) || layout?(path) || ignored?(path)
224
+ return true if @config[:plugins][:generators].has_key? path.extension
225
+ return true if File.open(path, "r").read(3) == "---"
226
+ false
227
+ end
228
+
229
+ # @return [Bool]
230
+ def ignored?( path )
231
+ ignored = ['/options.yaml'] + @config[:exclude]
232
+ ignored.collect! {|i| File.join(@config[:root], i)}
233
+ ignored.each do |i|
234
+ return true if path.include? i
235
+ end
236
+ false
237
+ end
212
238
 
213
239
  end
214
240
  end
@@ -11,10 +11,14 @@ module Henshin
11
11
  def to_hash
12
12
  hash = {
13
13
  'name' => @name,
14
- 'posts' => @posts.collect {|i| i.to_hash}
14
+ 'posts' => @posts.sort.collect {|i| i.to_hash},
15
+ 'url' => self.url
15
16
  }
16
17
  end
17
18
 
19
+ def url
20
+ "/tags/#{@name.slugify}/"
21
+ end
18
22
 
19
23
  def inspect
20
24
  "#<Tag:#{@name}>"
@@ -1,6 +1,3 @@
1
- // This is to test whether sass files are successfully created
2
- // and placed in the css folder (or whatever is defined
3
-
4
1
  body, div, dl, dt, dd, ul, ol, li, h1, h2, h3, h4, h5, h6, pre, form, fieldset, input, textarea, p, blockquote, th, td
5
2
  margin: 0
6
3
  padding: 0
@@ -1,5 +1,3 @@
1
- /* Testing whether static files, eg this, are correctly copied and ignored */
2
-
3
1
  body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,textarea,p,
4
2
  blockquote,th,td {margin:0; padding:0; }
5
3
  table { border-collapse:collapse; border-spacing:0; }
@@ -9,7 +7,6 @@ ol,ul { list-style:none; }
9
7
  caption,th { text-align:left; }
10
8
  h1,h2,h3,h4,h5,h6 { font-size:100%; font-weight:normal; }
11
9
  q:before,q:after { content:”; }
12
- abbr,acronym { border:0; }
13
- html {font-size: 62.5%;}p {font-size: 1.2em;}
10
+ abbr,acronym { border:0; }html {font-size: 62.5%;}p {font-size: 1.2em;}
14
11
  h1 {font-size: 2em;}
15
12
  a:hover, a:active { outline: none; }
@@ -0,0 +1,70 @@
1
+ @import includes/reset.css
2
+
3
+ body
4
+ width: 500px
5
+ margin: 20px
6
+ background: rgb(254, 254, 254)
7
+ line-height: 20px
8
+ font:
9
+ family: Helvetica, Arial, sans-serif
10
+ size: 16px
11
+
12
+ h1, h2
13
+ color: rgb(50, 50, 50)
14
+ line-height: 32px
15
+ font:
16
+ size: 22px
17
+ weight: bold
18
+
19
+ h2
20
+ font-size: 18px
21
+
22
+ p, ul, ol, pre
23
+ margin: 16px 0
24
+
25
+ a
26
+ color: rgb(20, 20, 180)
27
+
28
+ b, strong
29
+ font-weight: bold
30
+
31
+ i, em
32
+ font-style: italic
33
+
34
+ pre
35
+ background: rgb(240, 240, 245)
36
+ border: 1px solid rgb(200, 200, 202)
37
+
38
+ code
39
+ line-height: 13px
40
+ font:
41
+ family: Menlo
42
+ size: 13px
43
+
44
+ ul
45
+ time
46
+ font:
47
+ family: Menlo, monospace
48
+ size: 13px
49
+
50
+ &.tags
51
+ display: inline
52
+ li
53
+ float: left
54
+ margin: 0 5px
55
+
56
+
57
+
58
+ // code highlighting
59
+ code
60
+ .k
61
+ color: red
62
+
63
+ .nb
64
+ color: blue
65
+
66
+ .nf
67
+ color: green
68
+
69
+ .s2
70
+ color: grey