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
data/.gitignore CHANGED
@@ -20,4 +20,4 @@ pkg
20
20
  .yardoc
21
21
 
22
22
  ## PROJECT::SPECIFIC
23
- test/site/_site/
23
+ _site/
@@ -11,7 +11,6 @@ Henshin is a new static site generator, yeah another one. I wasn't going to rele
11
11
 
12
12
  ## Future Goals
13
13
 
14
- - Ability to regenerate only files that have changed
15
14
  - Easy tag, category and archive pages
16
15
  - Default templates so you can just type `henshin` with any folder of text files and create a quick site
17
16
 
data/Rakefile CHANGED
@@ -10,9 +10,12 @@ begin
10
10
  gem.email = "m@hawx.me"
11
11
  gem.homepage = "http://github.com/hawx/henshin"
12
12
  gem.authors = ["hawx"]
13
+ gem.add_dependency "titlecase", ">= 0.1.0"
14
+ gem.add_dependency "directory_watcher", ">= 1.3.1"
15
+ gem.add_dependency "maruku", ">= 0.6.0"
16
+ gem.add_dependency "liquid", ">= 2.0.0"
13
17
  gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
14
18
  gem.add_development_dependency "yard", ">= 0"
15
- # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
16
19
  end
17
20
  Jeweler::GemcutterTasks.new
18
21
  rescue LoadError
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.2
1
+ 0.3.0
@@ -0,0 +1,46 @@
1
+ opt_content = <<EOS
2
+ title: Test Site
3
+ author: John Doe
4
+ layout: main
5
+ EOS
6
+
7
+ index_content = <<EOS
8
+ ---
9
+ title: The Home Page
10
+ ---
11
+
12
+ Well you might want to change this!
13
+ EOS
14
+
15
+ layout_content = <<EOS
16
+ <!DOCTYPE html>
17
+ <html lang="en">
18
+ <head>
19
+ <meta charset="utf-8" />
20
+ <title>{{ site.title }}</title>
21
+ </head>
22
+ <body>
23
+
24
+ {{ yield }}
25
+
26
+ <h4>A List of Posts</h4>
27
+ <ul>
28
+ {% for post in site.posts %}
29
+ <li><a href="{{ post.url }}">{{ post.title }}</a> - {{ post.date }}</li>
30
+ {% endfor %}
31
+ </ul>
32
+
33
+ <span>Copyright &copy; {{ site.author }}</span>
34
+ </body>
35
+ </html>
36
+ EOS
37
+
38
+ post_content = <<EOS
39
+ ---
40
+ title: Hello World
41
+ date: #{Time.now.strftime("%Y-%m-%d at %H:%M:%S")}
42
+ tags: test, hello
43
+ ---
44
+
45
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
46
+ EOS
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require File.dirname(__FILE__) + '/../lib/henshin'
4
+ require File.dirname(__FILE__) + '/files.rb'
4
5
  require 'optparse'
5
6
  require 'fileutils'
6
7
 
@@ -14,53 +15,6 @@ Usage: henshin
14
15
 
15
16
  EOS
16
17
 
17
- opt_content = <<EOS
18
- title: Test Site
19
- author: John Doe
20
- layout: main
21
- EOS
22
-
23
- index_content = <<EOS
24
- ---
25
- title: The Home Page
26
- ---
27
-
28
- Well you might want to change this!
29
- EOS
30
-
31
- layout_content = <<EOS
32
- <!DOCTYPE html>
33
- <html lang="en">
34
- <head>
35
- <meta charset="utf-8" />
36
- <title>{{ site.title }}</title>
37
- </head>
38
- <body>
39
-
40
- {{ yield }}
41
-
42
- <h4>A List of Posts</h4>
43
- <ul>
44
- {% for post in site.posts %}
45
- <li><a href="{{ post.url }}">{{ post.title }}</a> - {{ post.date }}</li>
46
- {% endfor %}
47
- </ul>
48
-
49
- <span>Copyright &copy; {{ site.author }}</span>
50
- </body>
51
- </html>
52
- EOS
53
-
54
- post_content = <<EOS
55
- ---
56
- title: Hello World
57
- date: #{Time.now.strftime("%Y-%m-%d at %H:%M:%S")}
58
- tags: test, hello
59
- ---
60
-
61
- Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
62
- EOS
63
-
64
18
 
65
19
  if ARGV[0] == "create"
66
20
  if ARGV[1]
@@ -87,7 +41,7 @@ if ARGV[0] == "create"
87
41
  else
88
42
 
89
43
  override = {}
90
- build = {:server => false, :auto => false}
44
+ build = {:server => false, :auto => false, :port => 9991, :address => '0.0.0.0'}
91
45
  opts = OptionParser.new do |opts|
92
46
  opts.banner = banner
93
47
 
@@ -115,13 +69,45 @@ else
115
69
 
116
70
  config = Henshin.configure(override)
117
71
  site = Henshin::Site.new(config)
72
+ unless build[:auto]
73
+ start = Time.now
74
+ # build normally
75
+ puts "Building site..."
76
+ site.build
77
+ puts "Site created in #{config[:target]} (#{Time.now - start}s)"
78
+ end
118
79
 
119
- start = Time.now
120
- # build normally
121
- puts "Building site..."
122
- site.build
123
- puts "Site created in #{config[:target]} (#{Time.now - start}s)"
124
-
80
+ threads = []
81
+ # start a server
82
+ if build[:server]
83
+ begin
84
+ require 'mongrel'
85
+
86
+ threads << Thread.new {
87
+ @h = Mongrel::HttpServer.new(build[:address], build[:port])
88
+ @h.register "/", Mongrel::DirHandler.new("test/site/_site")
89
+ puts "Server launched at http://#{build[:address]}:#{build[:port]}"
90
+ trap("INT") {
91
+ @h.stop
92
+ puts "\n"
93
+ }
94
+ @h.run.join
95
+ }
96
+ rescue LoadError
97
+
98
+ require 'webrick'
99
+ threads << Thread.new {
100
+ server = WEBrick::HTTPServer.new(
101
+ :Port => build[:port],
102
+ :DocumentRoot => File.join(config[:root], config[:target]),
103
+ :MimeTypes => WEBrick::HTTPUtils::DefaultMimeTypes
104
+ )
105
+ trap("INT") { server.shutdown }
106
+ server.start
107
+ }
108
+
109
+ end
110
+ end
125
111
 
126
112
  # regenerate files when changed
127
113
  if build[:auto]
@@ -134,11 +120,11 @@ else
134
120
  ['/_site', '/plugins'].each do |r|
135
121
  gl = gl.select {|i| !i.include?( File.join(config[:root], r) )}
136
122
  end
137
- gl.collect! {|x| "#{x}/**/*"}
123
+ gl.collect! {|x| "#{x}/**/*"[config[:root].size+1..-1]}
138
124
  gl += ['*']
139
-
125
+
140
126
  dw = DirectoryWatcher.new config[:root], :glob => gl
141
- dw.interval = 2.0
127
+ dw.interval = 1
142
128
  dw.add_observer do |*args|
143
129
  if args.size > 1
144
130
  puts "rebuilding -> #{args.size} files"
@@ -146,30 +132,12 @@ else
146
132
  puts "rebuilding -> #{args[0].path}"
147
133
  end
148
134
  site.build
135
+ puts "rebuilt..."
149
136
  end
150
137
 
151
- dw.start
152
-
153
- unless build[:server]
154
- loop {sleep 1000}
155
- end
138
+ threads << Thread.new { dw.start }
139
+ loop { sleep 1000 } unless build[:server]
156
140
  end
157
-
158
-
159
- # start a server
160
- if build[:server]
161
- require 'webrick'
162
-
163
- server = WEBrick::HTTPServer.new(
164
- :Port => '3000',
165
- :DocumentRoot => File.join(config[:root], config[:target]),
166
- :MimeTypes => WEBrick::HTTPUtils::DefaultMimeTypes
167
- )
168
-
169
- thread = Thread.new { server.start }
170
- trap("INT") { server.shutdown }
171
-
172
- thread.join()
173
- end
174
141
 
142
+ threads.each {|t| t.join}
175
143
  end
@@ -5,15 +5,14 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{henshin}
8
- s.version = "0.2.2"
8
+ s.version = "0.3.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["hawx"]
12
- s.date = %q{2010-06-06}
13
- s.default_executable = %q{henshin}
12
+ s.date = %q{2010-06-22}
14
13
  s.description = %q{Henshin is a static site generator, with a plugin system and more}
15
14
  s.email = %q{m@hawx.me}
16
- s.executables = ["henshin"]
15
+ s.executables = ["files.rb", "henshin"]
17
16
  s.extra_rdoc_files = [
18
17
  "LICENSE",
19
18
  "README.markdown"
@@ -24,16 +23,18 @@ Gem::Specification.new do |s|
24
23
  "README.markdown",
25
24
  "Rakefile",
26
25
  "VERSION",
26
+ "bin/files.rb",
27
27
  "bin/henshin",
28
28
  "henshin.gemspec",
29
29
  "lib/henshin.rb",
30
+ "lib/henshin/archive.rb",
30
31
  "lib/henshin/categories.rb",
31
32
  "lib/henshin/ext.rb",
32
33
  "lib/henshin/gen.rb",
33
34
  "lib/henshin/plugin.rb",
35
+ "lib/henshin/plugins/highlight.rb",
34
36
  "lib/henshin/plugins/liquid.rb",
35
37
  "lib/henshin/plugins/maruku.rb",
36
- "lib/henshin/plugins/pygments.rb",
37
38
  "lib/henshin/plugins/sass.rb",
38
39
  "lib/henshin/plugins/textile.rb",
39
40
  "lib/henshin/post.rb",
@@ -41,14 +42,14 @@ Gem::Specification.new do |s|
41
42
  "lib/henshin/static.rb",
42
43
  "lib/henshin/tags.rb",
43
44
  "test/helper.rb",
44
- "test/site/_site/2010/10/20-testing-stuff/index.html",
45
- "test/site/_site/2010/5/15-lorem-ipsum/index.html",
46
- "test/site/_site/css/print.css",
47
- "test/site/_site/index.html",
48
- "test/site/_site/static.html",
49
- "test/site/css/print.sass",
50
- "test/site/css/screen.css",
45
+ "test/site/css/includes/reset.sass",
46
+ "test/site/css/print.css",
47
+ "test/site/css/screen.sass",
48
+ "test/site/includes/head.html",
51
49
  "test/site/index.html",
50
+ "test/site/layouts/archive_date.html",
51
+ "test/site/layouts/archive_month.html",
52
+ "test/site/layouts/archive_year.html",
52
53
  "test/site/layouts/category_index.html",
53
54
  "test/site/layouts/category_page.html",
54
55
  "test/site/layouts/main.html",
@@ -63,12 +64,17 @@ Gem::Specification.new do |s|
63
64
  "test/site/posts/lorem-ipsum.markdown",
64
65
  "test/site/posts/same-date.markdown",
65
66
  "test/site/static.html",
67
+ "test/test_archives.rb",
68
+ "test/test_categories.rb",
66
69
  "test/test_gens.rb",
67
70
  "test/test_henshin.rb",
68
71
  "test/test_layouts.rb",
69
72
  "test/test_options.rb",
70
73
  "test/test_posts.rb",
71
- "test/test_site.rb"
74
+ "test/test_site.rb",
75
+ "test/test_statics.rb",
76
+ "test/test_tags.rb",
77
+ "test/text_exts.rb"
72
78
  ]
73
79
  s.homepage = %q{http://github.com/hawx/henshin}
74
80
  s.rdoc_options = ["--charset=UTF-8"]
@@ -78,12 +84,17 @@ Gem::Specification.new do |s|
78
84
  s.test_files = [
79
85
  "test/helper.rb",
80
86
  "test/site/plugins/test.rb",
87
+ "test/test_archives.rb",
88
+ "test/test_categories.rb",
81
89
  "test/test_gens.rb",
82
90
  "test/test_henshin.rb",
83
91
  "test/test_layouts.rb",
84
92
  "test/test_options.rb",
85
93
  "test/test_posts.rb",
86
- "test/test_site.rb"
94
+ "test/test_site.rb",
95
+ "test/test_statics.rb",
96
+ "test/test_tags.rb",
97
+ "test/text_exts.rb"
87
98
  ]
88
99
 
89
100
  if s.respond_to? :specification_version then
@@ -91,13 +102,25 @@ Gem::Specification.new do |s|
91
102
  s.specification_version = 3
92
103
 
93
104
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
105
+ s.add_runtime_dependency(%q<titlecase>, [">= 0.1.0"])
106
+ s.add_runtime_dependency(%q<directory_watcher>, [">= 1.3.1"])
107
+ s.add_runtime_dependency(%q<maruku>, [">= 0.6.0"])
108
+ s.add_runtime_dependency(%q<liquid>, [">= 2.0.0"])
94
109
  s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
95
110
  s.add_development_dependency(%q<yard>, [">= 0"])
96
111
  else
112
+ s.add_dependency(%q<titlecase>, [">= 0.1.0"])
113
+ s.add_dependency(%q<directory_watcher>, [">= 1.3.1"])
114
+ s.add_dependency(%q<maruku>, [">= 0.6.0"])
115
+ s.add_dependency(%q<liquid>, [">= 2.0.0"])
97
116
  s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
98
117
  s.add_dependency(%q<yard>, [">= 0"])
99
118
  end
100
119
  else
120
+ s.add_dependency(%q<titlecase>, [">= 0.1.0"])
121
+ s.add_dependency(%q<directory_watcher>, [">= 1.3.1"])
122
+ s.add_dependency(%q<maruku>, [">= 0.6.0"])
123
+ s.add_dependency(%q<liquid>, [">= 2.0.0"])
101
124
  s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
102
125
  s.add_dependency(%q<yard>, [">= 0"])
103
126
  end
@@ -5,6 +5,9 @@ require 'time'
5
5
  require 'yaml'
6
6
  require 'pp'
7
7
 
8
+ # 3rd party
9
+ require 'titlecase'
10
+
8
11
  # library
9
12
  require 'henshin/site'
10
13
 
@@ -14,6 +17,7 @@ require 'henshin/static'
14
17
 
15
18
  require 'henshin/tags'
16
19
  require 'henshin/categories'
20
+ require 'henshin/archive'
17
21
  require 'henshin/ext'
18
22
 
19
23
 
@@ -34,15 +38,16 @@ module Henshin
34
38
  :exclude => [] }
35
39
 
36
40
 
37
- # Creates the configuration hash by merging defaults, supplied options and options read from the 'options.yaml' file. Then loads the plugins
41
+ # Creates the configuration hash by merging defaults, supplied options and options
42
+ # read from the 'options.yaml' file. Then loads the plugins and sorts them
38
43
  #
39
44
  # @param [Hash] override to override other set options
40
45
  # @return [Hash] the merged configuration hash
41
46
  def self.configure( override={} )
42
- config_file = (override[:root] || Defaults[:root]) + '/options.yaml'
47
+ config_file = File.join((override[:root] || Defaults[:root]), '/options.yaml')
43
48
 
44
49
  begin
45
- config = YAML.load_file( config_file ).to_options
50
+ config = YAML.load_file(config_file).to_options
46
51
  settings = Defaults.merge(config).merge(override)
47
52
  rescue => e
48
53
  $stderr.puts "\nCould not read configuration, falling back to defaults..."
@@ -50,66 +55,75 @@ module Henshin
50
55
  settings = Defaults.merge(override)
51
56
  end
52
57
 
53
-
54
-
55
- # find the options for plugins, if any
56
- settings.each do |k, v|
57
- if settings[:plugins].include? k.to_s
58
- settings[:plugin_options][k] = v.to_options
59
- end
60
- end
61
-
62
- loaded_plugins = Henshin.load_plugins( settings[:plugins], settings[:root], settings[:plugin_options] )
63
-
64
- settings[:plugins] = {:generators => {}, :layout_parsers => []}
65
- loaded_plugins.each do |plugin|
58
+ settings[:exclude] << '/_site' << '/plugins'
59
+ settings[:plugins] = Henshin.sort_plugins( Henshin.load_plugins(settings) )
60
+ settings
61
+ end
62
+
63
+ # Organises the plugins into generators and layout parses,
64
+ # then turns the generators into a hash with a key for each extension.
65
+ #
66
+ # @param [Array] plugins
67
+ # @return [Hash]
68
+ def self.sort_plugins(plugins)
69
+ r = {:generators => {}, :layout_parsers => []}
70
+ plugins.each do |plugin|
66
71
  if plugin.is_a? Generator
67
72
  plugin.extensions[:input].each do |ext|
68
- settings[:plugins][:generators][ext] = plugin
73
+ r[:generators][ext] = plugin
69
74
  end
70
- end
71
- if plugin.is_a? LayoutParser
72
- settings[:plugins][:layout_parsers] << plugin
75
+ elsif plugin.is_a? LayoutParser
76
+ r[:layout_parsers] << plugin
73
77
  end
74
78
  end
75
-
76
- settings
79
+ r
77
80
  end
78
81
 
79
-
80
- # Loads the specified plugins
82
+ # Loads the plugins, each plugin then calls Henshin.register!, and then we loop through
83
+ # the options and pass the options for the plugin to it.
81
84
  #
82
- # @param [Array] plugins list of plugins to load
85
+ # @param [Hash] settings of loaded so far
83
86
  # @return [Array] list of loaded plugin instances
84
- def self.load_plugins( to_load, root, opts={} )
87
+ def self.load_plugins(opts)
85
88
  plugins = []
86
- to_load.each do |l|
89
+ opts[:plugins].each do |l|
87
90
  begin
88
91
  require 'henshin/plugins/' + l
89
92
  rescue LoadError
90
- require File.join(root, 'plugins/', l)
93
+ require File.join(opts[:root], 'plugins/', l)
91
94
  end
92
95
  end
93
96
 
94
- # pass options to the plugins
95
97
  @registered_plugins.each do |plugin|
96
- if plugin.respond_to? :configure
97
- plugin.configure( opts[plugin.opts_name] )
98
+ if plugin[:opts] && opts[plugin[:opts]]
99
+ opts[plugin[:opts]].each do |k, v|
100
+ if k.to_s.include? 'dir'
101
+ opts[plugin[:opts]][k] = File.join(opts[:root], v)
102
+ end
103
+ end
104
+ plugin[:plugin].configure opts[plugin[:opts]]
98
105
  end
106
+ plugins << plugin[:plugin]
99
107
  end
100
- @registered_plugins
108
+
109
+ plugins
101
110
  end
102
111
 
103
- # Each plugin will call this method when loaded from #load_plugins, these plugins then populate @registered_plugins, which is returned from #load_plugins. Complicated? Maybe, but it works!
104
- def self.register!( plug )
112
+ # Each plugin will call this method when loaded from #load_plugins, these plugins then
113
+ # populate @registered_plugins, which is returned from #load_plugins.
114
+ #
115
+ # @param [Class] plugin to load
116
+ # @param [Symbol] options symbol to look up in settings hash
117
+ # @return [Array] plugins and options symbol in hashes
118
+ def self.register!( plug, opts=nil )
105
119
  @registered_plugins ||= []
106
- @registered_plugins << plug.new
120
+ @registered_plugins << {:plugin => plug.new, :opts => opts}
107
121
  end
108
122
 
109
123
 
110
124
  # @return [String] current version
111
125
  def self.version
112
- File.read( File.join(File.dirname(__FILE__), *%w[.. VERSION]) )
126
+ File.read( File.join(File.dirname(__FILE__), '..', 'VERSION') )
113
127
  end
114
128
 
115
129
  end