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
@@ -1,43 +0,0 @@
1
- class Hash
2
- # Cleans up the hash and returns the result. It performs the following
3
- # operations:
4
- #
5
- # * Values with keys ending in _at and _on are converted into Times and
6
- # Dates, respectively
7
- # * All keys are converted to symbols
8
- # * Value strings 'true', 'false', and 'none' are converted into
9
- # true, false, and nil, respectively
10
- def clean
11
- symbolize_keys.inject({}) do |hash, (key, value)|
12
- if key.to_s =~ /_on$/
13
- hash.merge(key => Date.parse(value))
14
- elsif key.to_s =~ /_at$/
15
- hash.merge(key => Time.parse(value))
16
- elsif value == 'true'
17
- hash.merge(key => true)
18
- elsif value == 'false'
19
- hash.merge(key => false)
20
- elsif value == 'none'
21
- hash.merge(key => nil)
22
- else
23
- hash.merge(key => value)
24
- end
25
- end
26
- end
27
-
28
- # Converts all keys in the hash to symbols and returns the result
29
- def symbolize_keys
30
- inject({}) do |hash, (key, value)|
31
- new_value = value.respond_to?(:symbolize_keys) ? value.symbolize_keys : value
32
- hash.merge({ key.to_sym => new_value })
33
- end
34
- end
35
-
36
- # Converts all keys in the hash to strings and returns the result
37
- def stringify_keys
38
- inject({}) do |hash, (key, value)|
39
- new_value = value.respond_to?(:stringify_keys) ? value.stringify_keys : value
40
- hash.merge({ key.to_s => new_value })
41
- end
42
- end
43
- end
@@ -1,13 +0,0 @@
1
- class String
2
-
3
- # Returns true if the string starts with str
4
- def starts_with?(str)
5
- str == self[0, str.length]
6
- end
7
-
8
- # Returns true if the string ends with str
9
- def ends_with?(str)
10
- str == self[-str.length, str.length]
11
- end
12
-
13
- end
@@ -1,10 +0,0 @@
1
- require 'yaml'
2
-
3
- module YAML
4
-
5
- # Loads a YAML file, cleans it using Hash#clean, and returns the result
6
- def self.load_file_and_clean(a_filename)
7
- (YAML.load_file(a_filename) || {}).clean
8
- end
9
-
10
- end
@@ -1,180 +0,0 @@
1
- module Nanoc
2
-
3
- class Creator
4
-
5
- def create_site(a_sitename)
6
- ensure_nonexistant(a_sitename)
7
-
8
- FileManager.create_dir a_sitename do
9
- FileManager.create_dir 'output'
10
-
11
- FileManager.create_file 'config.yaml' do
12
- "output_dir: \"output\"\n"
13
- end
14
-
15
- FileManager.create_file 'meta.yaml' do
16
- "# This file contains the default values for all metafiles.\n" +
17
- "# Other metafiles can override the contents of this one.\n" +
18
- "\n" +
19
- "# Built-in\n" +
20
- "layout: \"default\"\n" +
21
- "filters: []\n" +
22
- "filename: \"index\"\n" +
23
- "extension: \"html\"\n" +
24
- "\n" +
25
- "# Custom\n"
26
- end
27
-
28
- FileManager.create_file 'Rakefile' do
29
- "Dir['tasks/**/*.rake'].sort.each { |rakefile| load rakefile }\n" +
30
- "\n" +
31
- "task :default do\n" +
32
- " puts 'This is an example rake task.'\n" +
33
- "end\n"
34
- end
35
-
36
- FileManager.create_dir 'layouts' do
37
- FileManager.create_file 'default.erb' do
38
- "<html>\n" +
39
- " <head>\n" +
40
- " <title><%= @page.title %></title>\n" +
41
- " </head>\n" +
42
- " <body>\n" +
43
- "<%= @page.content %>\n" +
44
- " </body>\n" +
45
- "</html>\n"
46
- end
47
- end
48
-
49
- FileManager.create_dir 'lib' do
50
- FileManager.create_file 'default.rb' do
51
- "\# All files in the 'lib' directory will be loaded\n" +
52
- "\# before nanoc starts compiling.\n" +
53
- "\n" +
54
- "def html_escape(a_string)\n" +
55
- " a_string.gsub('&', '&amp;').gsub('<', '&lt;').gsub('>', '&gt;').gsub('\"', '&quot;')\n" +
56
- "end\n" +
57
- "alias h html_escape\n"
58
- end
59
- end
60
-
61
- FileManager.create_dir 'tasks' do
62
- FileManager.create_file 'default.rake' do
63
- "task :example do\n" +
64
- " puts 'This is an example rake task in tasks/default.rake.'\n" +
65
- "end\n"
66
- end
67
- end
68
-
69
- FileManager.create_dir 'templates' do
70
- FileManager.create_dir 'default' do
71
- FileManager.create_file "default.txt" do
72
- "This is a new page. Please edit me!\n"
73
- end
74
- FileManager.create_file 'meta.yaml' do
75
- "# Built-in\n" +
76
- "\n" +
77
- "# Custom\n" +
78
- "title: A New Page\n"
79
- end
80
- end
81
- end
82
-
83
- FileManager.create_dir 'content' do
84
- FileManager.create_file 'content.txt' do
85
- "This is a sample root page. Please edit me!\n"
86
- end
87
- FileManager.create_file 'meta.yaml' do
88
- "# Built-in\n" +
89
- "\n" +
90
- "# Custom\n" +
91
- "title: My New Homepage\n"
92
- end
93
- end
94
- end
95
- end
96
-
97
- def create_page(a_pagename, a_params={})
98
- Nanoc.ensure_in_site
99
- ensure_nonexistant(File.join(['content', a_pagename]))
100
-
101
- # Sanitize page name
102
- if a_pagename =~ /^[\/\.]+/
103
- $stderr.puts 'ERROR: page name starts with dots and/or slashes, aborting' unless $quiet
104
- return
105
- end
106
-
107
- # Read template
108
- template = a_params[:template] || 'default'
109
- begin
110
- template_meta = File.read("templates/#{template}/meta.yaml")
111
-
112
- # Find all files
113
- template_content_filenames = Dir["templates/#{template}/#{template}.*"]
114
-
115
- # Find all index.* files (used to be a fallback for nanoc 1.0, kinda...)
116
- template_content_filenames += Dir["templates/#{template}/index.*"]
117
-
118
- # Reject backups
119
- template_content_filenames.reject! { |f| f =~ /~$/ }
120
-
121
- # Make sure there is only one content file
122
- template_content_filenames.ensure_single('template files', template)
123
-
124
- # Get the first (and only one)
125
- template_content_filename = template_content_filenames[0]
126
-
127
- template_index = File.read(template_content_filename)
128
- rescue => e
129
- puts e.inspect
130
- $stderr.puts 'ERROR: no such template' unless $quiet
131
- exit
132
- end
133
- template_meta = template_meta.eruby
134
- template_index = template_index.eruby
135
-
136
- # Create index and yaml file
137
- FileManager.create_dir 'content' do
138
- FileManager.create_dir a_pagename do
139
- page_name = a_pagename.sub(/.*\/([^\/]+)/, '\1')
140
- extension = File.extname(template_content_filename)
141
- FileManager.create_file "#{page_name}#{extension}" do
142
- template_index
143
- end
144
- FileManager.create_file 'meta.yaml' do
145
- template_meta
146
- end
147
- end
148
- end
149
- end
150
-
151
- def create_template(a_templatename)
152
- Nanoc.ensure_in_site
153
- ensure_nonexistant(File.join(['templates', a_templatename]))
154
-
155
- FileManager.create_dir 'templates' do
156
- FileManager.create_dir a_templatename do
157
- FileManager.create_file "#{a_templatename}.txt" do
158
- "This is a new page. Please edit me!\n"
159
- end
160
- FileManager.create_file 'meta.yaml' do
161
- "# Built-in\n" +
162
- "\n" +
163
- "# Custom\n" +
164
- "title: A New Page\n"
165
- end
166
- end
167
- end
168
- end
169
-
170
- private
171
-
172
- def ensure_nonexistant(filename)
173
- if File.exist?(filename)
174
- $stderr.puts "ERROR: A file or directory named #{filename} already exists." unless $quiet
175
- exit
176
- end
177
- end
178
-
179
- end
180
- end
@@ -1,101 +0,0 @@
1
- def try_require(s)
2
- require s
3
- rescue LoadError
4
- end
5
-
6
- def nanoc_require(s)
7
- require s
8
- rescue LoadError
9
- $stderr.puts "ERROR: You need '#{s}' to compile this site." unless $quiet
10
- exit
11
- end
12
-
13
- try_require 'rubygems'
14
-
15
- require 'fileutils'
16
-
17
- def handle_exception(exception, text)
18
- unless $quiet or exception.class == SystemExit
19
- $stderr.puts "ERROR: Exception occured while #{text}:\n"
20
- $stderr.puts exception
21
- $stderr.puts exception.backtrace.join("\n")
22
- end
23
- exit(1)
24
- end
25
-
26
- class FileLogger
27
- COLORS = {
28
- :reset => "\e[0m",
29
-
30
- :bold => "\e[1m",
31
-
32
- :black => "\e[30m",
33
- :red => "\e[31m",
34
- :green => "\e[32m",
35
- :yellow => "\e[33m",
36
- :blue => "\e[34m",
37
- :magenta => "\e[35m",
38
- :cyan => "\e[36m",
39
- :white => "\e[37m"
40
- }
41
-
42
- ACTION_COLORS = {
43
- :create => COLORS[:bold] + COLORS[:green],
44
- :update => COLORS[:bold] + COLORS[:yellow],
45
- :move => COLORS[:bold] + COLORS[:blue],
46
- :identical => COLORS[:bold]
47
- }
48
-
49
- attr_reader :out
50
-
51
- def initialize(a_out = $stdout)
52
- @out = a_out
53
- end
54
-
55
- def log(a_action, a_path)
56
- @out.puts('%s%12s%s %s' % [ACTION_COLORS[a_action.to_sym], a_action, COLORS[:reset], a_path]) unless $quiet
57
- end
58
-
59
- private
60
-
61
- def method_missing(a_method, *a_args)
62
- log(a_method.to_s, a_args.first)
63
- end
64
- end
65
-
66
- class FileManager
67
- @@stack = []
68
- @@logger = FileLogger.new
69
-
70
- def self.create_dir(a_name)
71
- @@stack.pushing(a_name) do
72
- path = File.join(@@stack)
73
- unless File.directory?(path)
74
- FileUtils.mkdir_p(path)
75
- @@logger.create(path)
76
- end
77
- yield if block_given?
78
- end
79
- end
80
-
81
- def self.create_file(a_name)
82
- path = File.join(@@stack + [ a_name ])
83
- FileManager.create_dir(path.sub(/\/[^\/]+$/, '')) if @@stack.empty?
84
- content = block_given? ? yield : nil
85
- if File.exist?(path)
86
- if block_given? and File.read(path) == content
87
- @@logger.identical(path)
88
- else
89
- @@logger.update(path)
90
- end
91
- else
92
- @@logger.create(path)
93
- end
94
- open(path, 'w') { |io| io.write(content) unless content.nil? }
95
- end
96
- end
97
-
98
- def render(a_name, a_context={})
99
- assigns = a_context.merge({ :page => @page, :pages => @pages })
100
- File.read('layouts/' + a_name.to_s + '.erb').eruby(:assigns => assigns)
101
- end
@@ -1,7 +0,0 @@
1
- # Convenience function for registering filters
2
- def register_filter(*names, &block)
3
- names.each { |name| $nanoc_compiler.register_filter(name, &block) }
4
- end
5
-
6
- # Load all filters
7
- Dir[File.join(File.dirname(__FILE__), 'filters', '*_filter.rb')].each { |f| require f }
@@ -1,39 +0,0 @@
1
- class ERBContext
2
-
3
- def initialize(hash)
4
- hash.each_pair do |key, value|
5
- instance_variable_set('@' + key.to_s, value)
6
- end
7
- end
8
-
9
- def get_binding
10
- binding
11
- end
12
-
13
- end
14
-
15
- class String
16
-
17
- # Converts the string using eRuby
18
- def eruby(params={})
19
- params[:eruby_engine] == :erubis ? erubis(params) : erb(params)
20
- end
21
-
22
- # Converts the string using Erubis
23
- def erubis(params={})
24
- nanoc_require 'erubis'
25
- Erubis::Eruby.new(self).evaluate(params[:assigns] || {})
26
- end
27
-
28
- # Converts the string using ERB
29
- def erb(params={})
30
- nanoc_require 'erb'
31
- ERB.new(self).result(ERBContext.new(params[:assigns] || {}).get_binding)
32
- end
33
-
34
- end
35
-
36
- register_filter 'eruby' do |page, pages, config|
37
- assigns = { :page => page, :pages => pages }
38
- page.content.eruby(:assigns => assigns, :eruby_engine => config[:eruby_engine])
39
- end
@@ -1,18 +0,0 @@
1
- class String
2
-
3
- # Converts the string using Haml
4
- def haml(params={})
5
- nanoc_require 'haml'
6
-
7
- options = (params[:haml_options] || {})
8
- options[:locals] = params[:assigns] unless params[:assigns].nil?
9
-
10
- Haml::Engine.new(self, options).to_html
11
- end
12
-
13
- end
14
-
15
- register_filter 'haml' do |page, pages, config|
16
- assigns = { :page => page, :pages => pages }
17
- page.content.haml(:assigns => assigns, :haml_options => page[:haml_options])
18
- end
@@ -1,47 +0,0 @@
1
- # Filter
2
-
3
- class String
4
-
5
- def liquid(params={})
6
- nanoc_require 'liquid'
7
-
8
- Liquid::Template.parse(self).render((params[:assigns] || {}).stringify_keys)
9
- end
10
-
11
- end
12
-
13
- register_filter 'liquid' do |page, pages, config|
14
- assigns = { :page => page, :pages => pages }
15
- page.content.liquid(:assigns => assigns)
16
- end
17
-
18
- # Render tag
19
-
20
- begin
21
- class Nanoc::LiquidRenderTag < ::Liquid::Tag
22
- Syntax = /(['"])([^'"]+)\1/
23
-
24
- def initialize(markup, tokens)
25
- if markup =~ Syntax
26
- @layout_name = $2
27
- else
28
- raise SyntaxError.new("Error in tag 'render' - Valid syntax: render '[layout]'")
29
- end
30
-
31
- super
32
- end
33
-
34
- def parse(tokens)
35
- end
36
-
37
- def render(context)
38
- source = File.read('layouts/' + @layout_name + '.liquid')
39
- partial = Liquid::Template.parse(source)
40
-
41
- partial.render(context)
42
- end
43
- end
44
-
45
- Liquid::Template.register_tag('render', Nanoc::LiquidRenderTag)
46
- rescue NameError
47
- end