nanoc 1.6.2 → 2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/ChangeLog +27 -0
  2. data/Rakefile +34 -27
  3. data/bin/nanoc +153 -49
  4. data/lib/nanoc.rb +15 -33
  5. data/lib/nanoc/base/auto_compiler.rb +124 -0
  6. data/lib/nanoc/base/compiler.rb +55 -0
  7. data/lib/nanoc/base/core_ext/hash.rb +34 -0
  8. data/lib/nanoc/base/data_source.rb +53 -0
  9. data/lib/nanoc/base/enhancements.rb +89 -0
  10. data/lib/nanoc/base/filter.rb +16 -0
  11. data/lib/nanoc/base/layout_processor.rb +33 -0
  12. data/lib/nanoc/base/page.rb +155 -0
  13. data/lib/nanoc/base/page_proxy.rb +31 -0
  14. data/lib/nanoc/base/plugin.rb +19 -0
  15. data/lib/nanoc/base/plugin_manager.rb +33 -0
  16. data/lib/nanoc/base/site.rb +143 -0
  17. data/lib/nanoc/data_sources/database.rb +259 -0
  18. data/lib/nanoc/data_sources/filesystem.rb +308 -0
  19. data/lib/nanoc/data_sources/trivial.rb +145 -0
  20. data/lib/nanoc/filters/erb.rb +34 -0
  21. data/lib/nanoc/filters/haml.rb +16 -0
  22. data/lib/nanoc/filters/markaby.rb +15 -0
  23. data/lib/nanoc/filters/markdown.rb +13 -0
  24. data/lib/nanoc/filters/rdoc.rb +14 -0
  25. data/lib/nanoc/filters/smartypants.rb +13 -0
  26. data/lib/nanoc/filters/textile.rb +13 -0
  27. data/lib/nanoc/layout_processors/erb.rb +35 -0
  28. data/lib/nanoc/layout_processors/haml.rb +18 -0
  29. data/lib/nanoc/layout_processors/markaby.rb +16 -0
  30. metadata +37 -30
  31. data/lib/nanoc/compiler.rb +0 -145
  32. data/lib/nanoc/core_ext.rb +0 -1
  33. data/lib/nanoc/core_ext/array.rb +0 -17
  34. data/lib/nanoc/core_ext/hash.rb +0 -43
  35. data/lib/nanoc/core_ext/string.rb +0 -13
  36. data/lib/nanoc/core_ext/yaml.rb +0 -10
  37. data/lib/nanoc/creator.rb +0 -180
  38. data/lib/nanoc/enhancements.rb +0 -101
  39. data/lib/nanoc/filters.rb +0 -7
  40. data/lib/nanoc/filters/eruby_filter.rb +0 -39
  41. data/lib/nanoc/filters/haml_filter.rb +0 -18
  42. data/lib/nanoc/filters/liquid_filter.rb +0 -47
  43. data/lib/nanoc/filters/markaby_filter.rb +0 -15
  44. data/lib/nanoc/filters/markdown_filter.rb +0 -13
  45. data/lib/nanoc/filters/rdoc_filter.rb +0 -15
  46. data/lib/nanoc/filters/sass_filter.rb +0 -13
  47. data/lib/nanoc/filters/smartypants_filter.rb +0 -13
  48. data/lib/nanoc/filters/textile_filter.rb +0 -13
  49. data/lib/nanoc/page.rb +0 -171
  50. data/lib/nanoc/page_drop.rb +0 -18
  51. data/lib/nanoc/page_proxy.rb +0 -30
data/ChangeLog CHANGED
@@ -1,6 +1,33 @@
1
1
  nanoc Release Notes
2
2
  ===================
3
3
 
4
+ 2.0
5
+ ---
6
+
7
+ New:
8
+
9
+ * Support for custom layout processors
10
+ * Support for custom data sources
11
+ * Database data source
12
+ * Auto-compiler
13
+ * Pages have `parent` and `children`
14
+
15
+ Changed:
16
+
17
+ * The source has been restructured and cleaned up a great deal
18
+ * Filters are defined in a different way now
19
+ * The 'eruby' filter now uses ERB instead of Erubis
20
+
21
+ Removed:
22
+
23
+ * The `filters` property; use `filters_pre` instead
24
+ * Support for Liquid
25
+
26
+ 1.6.2
27
+ -----
28
+
29
+ * Fixed an issue which prevented the content capturing plugin from working
30
+
4
31
  1.6.1
5
32
  -----
6
33
 
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ ##### Requirements
2
+
1
3
  require 'rake'
2
4
 
3
5
  require 'rake/clean'
@@ -6,50 +8,47 @@ require 'rake/testtask'
6
8
 
7
9
  require File.dirname(__FILE__) + '/lib/nanoc.rb'
8
10
 
9
- #####
11
+ ##### General details
10
12
 
11
13
  NAME = 'nanoc'
12
14
  VERS = Nanoc::VERSION
13
- SUMMARY = 'a CMS that doesn\'t run on your server'
14
-
15
+ SUMMARY = 'a tool that runs on your local computer and compiles Markdown, ' +
16
+ 'Textile, Haml, ... documents into static web pages'
15
17
  HOMEPAGE = 'http://nanoc.stoneship.org/'
18
+
19
+ AUTHOR = 'Denis Defreyne'
16
20
  EMAIL = 'denis.defreyne@stoneship.org'
17
21
 
18
- #####
22
+ ##### Cleaning
19
23
 
20
24
  CLEAN.include [ 'tmp', 'test/fixtures/*/output/*', 'test/fixtures/*/tmp' ]
21
25
  CLOBBER.include [ 'pkg' ]
22
26
 
27
+ ##### Packaging
28
+
23
29
  spec = Gem::Specification.new do |s|
24
- s.name = NAME
25
- s.version = VERS
26
- s.platform = Gem::Platform::RUBY
27
- s.summary = SUMMARY
28
- s.description = s.summary
29
- s.homepage = HOMEPAGE
30
- s.email = EMAIL
30
+ s.name = NAME
31
+ s.version = VERS
32
+ s.platform = Gem::Platform::RUBY
33
+ s.summary = SUMMARY
34
+ s.description = s.summary
35
+ s.homepage = HOMEPAGE
31
36
 
32
- s.required_ruby_version = '>= 1.8.2'
37
+ s.author = AUTHOR
38
+ s.email = EMAIL
33
39
 
34
- s.has_rdoc = false
35
- s.files = %w( README LICENSE ChangeLog Rakefile ) + Dir['{bin,lib}/**/*']
36
- s.executables = [ 'nanoc' ]
37
- s.require_path = 'lib'
38
- s.bindir = 'bin'
39
- end
40
+ s.rubyforge_project = 'nanoc'
40
41
 
41
- Rake::GemPackageTask.new(spec) do |task|
42
- task.need_tar = true
43
- task.gem_spec = spec
44
- end
42
+ s.required_ruby_version = '>= 1.8.2'
45
43
 
46
- Rake::TestTask.new(:test) do |test|
47
- test.test_files = Dir['test/test_*.rb']
44
+ s.has_rdoc = false
45
+ s.files = %w( README LICENSE ChangeLog Rakefile ) + Dir['{bin,lib}/**/*']
46
+ s.executables = [ 'nanoc' ]
47
+ s.require_path = 'lib'
48
+ s.bindir = 'bin'
48
49
  end
49
50
 
50
- #####
51
-
52
- task :default => [ :test ]
51
+ Rake::GemPackageTask.new(spec) { |task| }
53
52
 
54
53
  task :install_gem do
55
54
  sh %{rake package}
@@ -59,3 +58,11 @@ end
59
58
  task :uninstall_gem do
60
59
  sh %{sudo gem uninstall #{NAME}}
61
60
  end
61
+
62
+ ### Testing
63
+
64
+ Rake::TestTask.new(:test) do |test|
65
+ test.test_files = Dir['test/test_*.rb']
66
+ end
67
+
68
+ task :default => [ :test ]
data/bin/nanoc CHANGED
@@ -1,26 +1,35 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require File.dirname(__FILE__) + '/../lib/nanoc.rb'
3
+ # Get what we need
4
4
 
5
+ require File.dirname(__FILE__) + '/../lib/nanoc.rb'
5
6
  require 'getoptlong'
6
7
 
7
- try_require 'rubygems'
8
+ # Helper functions
9
+
10
+ def usage(s)
11
+ error(s, 'Usage')
12
+ end
8
13
 
9
14
  # Define some texts
15
+
10
16
  version_text = "nanoc #{Nanoc::VERSION} (c) 2007 Denis Defreyne."
11
- usage_text = "Usage: nanoc [options] [command] [parameters]"
12
17
  help_text = <<EOT
13
- Usage: nanoc [-chv]
14
- nanoc create_site <name>
15
- nanoc create_page <name> [-t template]
16
- nanoc create_template <name>
18
+ Usage: nanoc [-chvV]
17
19
  nanoc compile
20
+ nanoc autocompile
21
+ nanoc create_layout [layout_name]
22
+ nanoc create_page [page_name] [-t template]
23
+ nanoc create_site [site_name]
24
+ nanoc create_template [template_name]
18
25
 
19
26
  Options:
20
- -h, --help Show this help message and quit.
21
- -v, --version Show the nanoc version number and quit.
22
- -t, --template Template that should be used when creating a page.
23
- (can only be used with create_page)
27
+ -h, --help Show this help message and quit.
28
+ -p, --port Port the autocompiler should be run on.
29
+ -t, --template Template that should be used when creating a page.
30
+ (can only be used with create_page)
31
+ -V, --verbose Display more verbose log messages.
32
+ -v, --version Show the nanoc version number and quit.
24
33
 
25
34
  Description:
26
35
  The 'nanoc' command is used for creating nanoc-powered sites, as well as
@@ -29,72 +38,167 @@ Description:
29
38
  Read more about nanoc on the site: <http://nanoc.stoneship.org/>
30
39
  EOT
31
40
 
41
+ # Create site
42
+
43
+ $nanoc_site = Nanoc::Site.from_cwd
44
+
32
45
  # Parse options
46
+
33
47
  opts = GetoptLong.new(
34
- [ '--help', '-h', GetoptLong::NO_ARGUMENT ],
35
- [ '--template', '-t', GetoptLong::REQUIRED_ARGUMENT ],
36
- [ '--version', '-v', GetoptLong::NO_ARGUMENT ]
48
+ [ '--help', '-h', GetoptLong::NO_ARGUMENT ],
49
+ [ '--port', '-p', GetoptLong::REQUIRED_ARGUMENT ],
50
+ [ '--template', '-t', GetoptLong::REQUIRED_ARGUMENT ],
51
+ [ '--verbose', '-V', GetoptLong::NO_ARGUMENT ],
52
+ [ '--version', '-v', GetoptLong::NO_ARGUMENT ],
53
+ [ '--yes', '-y', GetoptLong::NO_ARGUMENT ]
37
54
  )
38
- unprocessed_opts = {}
55
+ $unprocessed_opts = {}
39
56
  begin
40
57
  opts.each do |opt, arg|
41
58
  case opt
42
59
  when '--help'
43
60
  $stderr.puts help_text
44
61
  exit
62
+ when '--verbose'
63
+ $log_level = :low
45
64
  when '--version'
46
65
  puts version_text
47
66
  exit
48
67
  else
49
- unprocessed_opts[opt] = arg
68
+ $unprocessed_opts[opt] = arg
50
69
  end
51
70
  end
52
71
  rescue GetoptLong::InvalidOption
53
72
  $stderr.puts usage_text
54
- exit
73
+ exit(1)
55
74
  end
56
75
 
57
76
  # Make sure we have at least one argument
58
- if ARGV.size == 0
59
- $stderr.puts usage_text
60
- exit
77
+
78
+ usage 'nanoc [options] [command] [parameters]' if ARGV.size == 0
79
+
80
+ # Functions for handing commands
81
+
82
+ def setup
83
+ # Check syntax
84
+ usage 'Usage: nanoc setup' if ARGV.size != 1
85
+
86
+ # Make sure we are in a nanoc site directory
87
+ unless $nanoc_site
88
+ error 'The current working directory does not seem to ' +
89
+ 'be a valid/complete nanoc site directory; aborting.'
90
+ end
91
+
92
+ # Check for -y switch
93
+ unless $unprocessed_opts.has_key?('--yes')
94
+ error 'Are you absolutely sure you want to set up the data source for ' +
95
+ 'this site? Setting up the data source will remove existing ' +
96
+ 'data. To continue, use the -y switch, like "nanoc setup -y".'
97
+ end
98
+
99
+ # Setup
100
+ $nanoc_site.setup
61
101
  end
62
102
 
63
- # Handle command
64
- command = ARGV[0]
65
- case command
103
+ def create_site
104
+ # Check syntax
105
+ usage 'Usage: nanoc create_site [site_name] [options]' if ARGV.size != 2
106
+
66
107
  # Create site
67
- when 'create_site', 'cs'
68
- if ARGV.size != 2
69
- $stderr.puts 'Usage: nanoc create_site [site_name]'
70
- exit
71
- end
72
- $nanoc_creator.create_site(ARGV[1])
108
+ Nanoc::Site.create(ARGV[1])
109
+ end
110
+
111
+ def create_page
112
+ # Check syntax
113
+ usage 'Usage: nanoc create_page [page_name] [options]' if ARGV.size != 2
114
+
115
+ # Make sure we are in a nanoc site directory
116
+ unless $nanoc_site
117
+ error 'The current working directory does not seem to ' +
118
+ 'be a valid/complete nanoc site directory; aborting.'
119
+ end
73
120
 
74
121
  # Create page
75
- when 'create_page', 'cp'
76
- if ARGV.size != 2
77
- $stderr.puts 'Usage: nanoc create_page [page_name]'
78
- exit
79
- end
80
- $nanoc_creator.create_page(ARGV[1], :template => unprocessed_opts['--template'])
122
+ if $unprocessed_opts['--template'].nil?
123
+ $nanoc_site.create_page(ARGV[1])
124
+ else
125
+ $nanoc_site.create_page(ARGV[1], $unprocessed_opts['--template'])
126
+ end
127
+ end
128
+
129
+ def create_layout
130
+ # Check syntax
131
+ usage 'nanoc create_layout [layout_name]' if ARGV.size != 2
132
+
133
+ # Make sure we are in a nanoc site directory
134
+ unless $nanoc_site
135
+ error 'The current working directory does not seem to ' +
136
+ 'be a valid/complete nanoc site directory; aborting.'
137
+ end
81
138
 
82
139
  # Create template
83
- when 'create_template', 'ct'
84
- if ARGV.size != 2
85
- $stderr.puts 'Usage: nanoc create_template [template_name]'
86
- exit
87
- end
88
- $nanoc_creator.create_template(ARGV[1])
140
+ $nanoc_site.create_layout(ARGV[1])
141
+ end
89
142
 
90
- # Process site and generate output
91
- when 'compile', 'compile_site', 'co'
92
- if ARGV.size != 1
93
- $stderr.puts 'Usage: nanoc compile'
94
- exit
95
- end
96
- $nanoc_compiler.run
143
+ def create_template
144
+ # Check syntax
145
+ usage 'nanoc create_template [template_name]' if ARGV.size != 2
146
+
147
+ # Make sure we are in a nanoc site directory
148
+ unless $nanoc_site
149
+ error 'The current working directory does not seem to ' +
150
+ 'be a valid/complete nanoc site directory; aborting.'
151
+ end
152
+
153
+ # Create template
154
+ $nanoc_site.create_template(ARGV[1])
155
+ end
97
156
 
157
+ def compile_site
158
+ # Check syntax
159
+ usage 'nanoc compile' if ARGV.size != 1
160
+
161
+ # Make sure we are in a nanoc site directory
162
+ unless $nanoc_site
163
+ error 'The current working directory does not seem to ' +
164
+ 'be a valid/complete nanoc site directory; aborting.'
165
+ end
166
+
167
+ # Compile site
168
+ $nanoc_site.compile
169
+ end
170
+
171
+ def autocompile_site
172
+ # Check syntax
173
+ usage 'nanoc compile' if ARGV.size != 1
174
+
175
+ # Make sure we are in a nanoc site directory
176
+ unless $nanoc_site
177
+ error 'The current working directory does not seem to ' +
178
+ 'be a valid/complete nanoc site directory; aborting.'
179
+ end
180
+
181
+ # Autocompile site
182
+ $nanoc_site.autocompile($unprocessed_opts['--port'])
183
+ end
184
+
185
+ # Handle command
186
+
187
+ case ARGV[0]
188
+ when 'autocompile_site', 'autocompile', 'aco'
189
+ autocompile_site
190
+ when 'create_site', 'cs'
191
+ create_site
192
+ when 'create_page', 'cp'
193
+ create_page
194
+ when 'create_layout', 'cl'
195
+ create_layout
196
+ when 'create_template', 'ct'
197
+ create_template
198
+ when 'compile_site', 'compile', 'co'
199
+ compile_site
200
+ when 'setup', 's'
201
+ setup
98
202
  else
99
- puts 'Unrecognised command \'' + command + '\''
203
+ error 'Unrecognised command \'' + ARGV[0] + '\''
100
204
  end
@@ -1,42 +1,24 @@
1
1
  module Nanoc
2
2
 
3
- VERSION = '1.6.2'
3
+ VERSION = '2.0'
4
4
 
5
- def self.ensure_in_site
6
- unless in_site?
7
- $stderr.puts 'ERROR: The current working directory does not seem to ' +
8
- 'be a valid/complete nanoc site directory; aborting.' unless $quiet
9
- exit
10
- end
11
- end
12
-
13
- private
14
-
15
- def self.in_site?
16
- return false unless File.directory?('content')
17
- return false unless File.directory?('layouts')
18
- return false unless File.directory?('lib')
19
- return false unless File.directory?('tasks')
20
- return false unless File.directory?('templates')
21
- return false unless File.exist?('config.yaml')
22
- return false unless File.exist?('meta.yaml')
23
- return false unless File.exist?('Rakefile')
24
-
25
- true
5
+ def self.load_file(*path)
6
+ full_path = [ File.dirname(__FILE__), 'nanoc' ] + path
7
+ Dir[File.join(full_path)].each { |f| require f }
26
8
  end
27
9
 
28
10
  end
29
11
 
30
- require File.dirname(__FILE__) + '/nanoc/enhancements.rb'
31
-
32
- require File.dirname(__FILE__) + '/nanoc/creator.rb'
33
- require File.dirname(__FILE__) + '/nanoc/compiler.rb'
12
+ # Load base
13
+ Nanoc.load_file('base', 'enhancements.rb')
14
+ Nanoc.load_file('base', 'core_ext', '*.rb')
15
+ Nanoc.load_file('base', 'plugin.rb')
16
+ Nanoc.load_file('base', '*.rb')
34
17
 
35
- $nanoc_creator = Nanoc::Creator.new
36
- $nanoc_compiler = Nanoc::Compiler.new
18
+ # Load plugins
19
+ Nanoc.load_file('data_sources', '*.rb')
20
+ Nanoc.load_file('filters', '*.rb')
21
+ Nanoc.load_file('layout_processors', '*.rb')
37
22
 
38
- require File.dirname(__FILE__) + '/nanoc/core_ext.rb'
39
- require File.dirname(__FILE__) + '/nanoc/filters.rb'
40
- require File.dirname(__FILE__) + '/nanoc/page.rb'
41
- require File.dirname(__FILE__) + '/nanoc/page_drop.rb'
42
- require File.dirname(__FILE__) + '/nanoc/page_proxy.rb'
23
+ # Get global binding
24
+ $nanoc_binding = binding
@@ -0,0 +1,124 @@
1
+ require 'webrick'
2
+
3
+ module Nanoc
4
+
5
+ class AutoCompiler
6
+
7
+ ERROR_404 = <<END
8
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
9
+ <html>
10
+ <head>
11
+ <title>404 File Not Found</title>
12
+ <style type="text/css">
13
+ body { padding: 10px; border: 10px solid #f00; margin: 10px; font-family: Helvetica, Arial, sans-serif; }
14
+ </style>
15
+ </head>
16
+ <body>
17
+ <h1>404 File Not Found</h1>
18
+ <p>The file you requested, <i><%=h path %></i>, was not found on this server.</p>
19
+ </body>
20
+ </html>
21
+ END
22
+
23
+ ERROR_500 = <<END
24
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
25
+ <html>
26
+ <head>
27
+ <title>500 Server Error</title>
28
+ <style type="text/css">
29
+ body { padding: 10px; border: 10px solid #f00; margin: 10px; font-family: Helvetica, Arial, sans-serif; }
30
+ </style>
31
+ </head>
32
+ <body>
33
+ <h1>500 Server Error</h1>
34
+ <p>An error occurred while compiling the page you requested, <i><%=h path %></i>.</p>
35
+ <p>If you think this is a bug in nanoc, please do <a href="http://nanoc.stoneship.org/trac/newticket">report it</a>&mdash;thanks!</p>
36
+ <p>Message:</p>
37
+ <blockquote><p><%=h exception.message %></p></blockquote>
38
+ <p>Backtrace:</p>
39
+ <ol>
40
+ <% exception.backtrace.each do |line| %>
41
+ <li><%= line %></li>
42
+ <% end %>
43
+ </ol>
44
+ </body>
45
+ </html>
46
+ END
47
+
48
+ def initialize(site)
49
+ # Set site
50
+ @site = site
51
+ end
52
+
53
+ def start(port)
54
+ nanoc_require('mime/types', "'mime/types' is required to autocompile sites.")
55
+
56
+ # Create server
57
+ @server = WEBrick::HTTPServer.new(:Port => port || 3000)
58
+ @server.mount_proc("/") { |request, response| handle_request(request, response) }
59
+
60
+ # Start server
61
+ trap('INT') { @server.shutdown }
62
+ @server.start
63
+ end
64
+
65
+ def handle_request(request, response)
66
+ # Reload site data
67
+ @site.load_data(true)
68
+
69
+ # Get page or file
70
+ page = @site.pages.find { |page| page.path == request.path }
71
+ file_path = @site.config[:output_dir] + request.path
72
+
73
+ if page.nil?
74
+ # Serve file
75
+ if File.exist?(file_path)
76
+ serve_file(file_path, response)
77
+ else
78
+ serve_404(request.path, response)
79
+ end
80
+ else
81
+ # Serve page
82
+ serve_page(page, response)
83
+ end
84
+ end
85
+
86
+ def h(s)
87
+ ERB::Util.html_escape(s)
88
+ end
89
+
90
+ def serve_404(path, response)
91
+ response.status = 404
92
+ response['Content-Type'] = 'text/html'
93
+ response.body = ERB.new(ERROR_404).result(binding)
94
+ end
95
+
96
+ def serve_500(path, exception, response)
97
+ response.status = 500
98
+ response['Content-Type'] = 'text/html'
99
+ response.body = ERB.new(ERROR_500).result(binding)
100
+ end
101
+
102
+ def serve_file(path, response)
103
+ response.status = 200
104
+ response['Content-Type'] = MIME::Types.of(path).first || 'application/octet-stream'
105
+ response.body = File.read(path)
106
+ end
107
+
108
+ def serve_page(page, response)
109
+ # Recompile page
110
+ begin
111
+ @site.compiler.run(page)
112
+ rescue => exception
113
+ serve_500(page.path, exception, response)
114
+ return
115
+ end
116
+
117
+ response.status = 200
118
+ response['Content-Type'] = 'text/html'
119
+ response.body = page.layouted_content
120
+ end
121
+
122
+ end
123
+
124
+ end