nanoc 1.6.2 → 2.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.
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