nanoc 2.0 → 2.1

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 (99) hide show
  1. data/ChangeLog +54 -0
  2. data/LICENSE +1 -1
  3. data/README +63 -3
  4. data/Rakefile +61 -14
  5. data/bin/nanoc +7 -199
  6. data/lib/nanoc/base/asset.rb +113 -0
  7. data/lib/nanoc/base/asset_defaults.rb +21 -0
  8. data/lib/nanoc/base/asset_rep.rb +277 -0
  9. data/lib/nanoc/base/binary_filter.rb +44 -0
  10. data/lib/nanoc/base/code.rb +41 -0
  11. data/lib/nanoc/base/compiler.rb +46 -34
  12. data/lib/nanoc/base/core_ext/hash.rb +51 -7
  13. data/lib/nanoc/base/core_ext/string.rb +8 -0
  14. data/lib/nanoc/base/data_source.rb +253 -20
  15. data/lib/nanoc/base/defaults.rb +30 -0
  16. data/lib/nanoc/base/enhancements.rb +9 -84
  17. data/lib/nanoc/base/filter.rb +109 -6
  18. data/lib/nanoc/base/layout.rb +91 -0
  19. data/lib/nanoc/base/notification_center.rb +66 -0
  20. data/lib/nanoc/base/page.rb +94 -121
  21. data/lib/nanoc/base/page_defaults.rb +20 -0
  22. data/lib/nanoc/base/page_rep.rb +318 -0
  23. data/lib/nanoc/base/plugin.rb +57 -9
  24. data/lib/nanoc/base/proxies/asset_proxy.rb +29 -0
  25. data/lib/nanoc/base/proxies/asset_rep_proxy.rb +26 -0
  26. data/lib/nanoc/base/proxies/layout_proxy.rb +25 -0
  27. data/lib/nanoc/base/proxies/page_proxy.rb +35 -0
  28. data/lib/nanoc/base/proxies/page_rep_proxy.rb +28 -0
  29. data/lib/nanoc/base/proxy.rb +37 -0
  30. data/lib/nanoc/base/router.rb +72 -0
  31. data/lib/nanoc/base/site.rb +220 -91
  32. data/lib/nanoc/base/template.rb +64 -0
  33. data/lib/nanoc/binary_filters/image_science_thumbnail.rb +28 -0
  34. data/lib/nanoc/cli/base.rb +219 -0
  35. data/lib/nanoc/cli/cli.rb +16 -0
  36. data/lib/nanoc/cli/command.rb +105 -0
  37. data/lib/nanoc/cli/commands/autocompile.rb +80 -0
  38. data/lib/nanoc/cli/commands/compile.rb +273 -0
  39. data/lib/nanoc/cli/commands/create_layout.rb +85 -0
  40. data/lib/nanoc/cli/commands/create_page.rb +85 -0
  41. data/lib/nanoc/cli/commands/create_site.rb +327 -0
  42. data/lib/nanoc/cli/commands/create_template.rb +76 -0
  43. data/lib/nanoc/cli/commands/help.rb +69 -0
  44. data/lib/nanoc/cli/commands/info.rb +114 -0
  45. data/lib/nanoc/cli/commands/switch.rb +141 -0
  46. data/lib/nanoc/cli/commands/update.rb +91 -0
  47. data/lib/nanoc/cli/ext.rb +37 -0
  48. data/lib/nanoc/cli/logger.rb +66 -0
  49. data/lib/nanoc/cli/option_parser.rb +168 -0
  50. data/lib/nanoc/cli.rb +1 -0
  51. data/lib/nanoc/data_sources/filesystem.rb +650 -215
  52. data/lib/nanoc/data_sources/filesystem_combined.rb +495 -0
  53. data/lib/nanoc/extra/auto_compiler.rb +265 -0
  54. data/lib/nanoc/extra/context.rb +22 -0
  55. data/lib/nanoc/extra/core_ext/hash.rb +54 -0
  56. data/lib/nanoc/extra/core_ext/time.rb +13 -0
  57. data/lib/nanoc/extra/file_proxy.rb +29 -0
  58. data/lib/nanoc/extra/vcs.rb +48 -0
  59. data/lib/nanoc/extra/vcses/bazaar.rb +21 -0
  60. data/lib/nanoc/extra/vcses/dummy.rb +20 -0
  61. data/lib/nanoc/extra/vcses/git.rb +21 -0
  62. data/lib/nanoc/extra/vcses/mercurial.rb +21 -0
  63. data/lib/nanoc/extra/vcses/subversion.rb +21 -0
  64. data/lib/nanoc/filters/bluecloth.rb +13 -0
  65. data/lib/nanoc/filters/erb.rb +6 -22
  66. data/lib/nanoc/filters/erubis.rb +14 -0
  67. data/lib/nanoc/filters/haml.rb +11 -6
  68. data/lib/nanoc/filters/markaby.rb +5 -5
  69. data/lib/nanoc/filters/maruku.rb +14 -0
  70. data/lib/nanoc/filters/old.rb +19 -0
  71. data/lib/nanoc/filters/rdiscount.rb +13 -0
  72. data/lib/nanoc/filters/rdoc.rb +5 -4
  73. data/lib/nanoc/filters/redcloth.rb +14 -0
  74. data/lib/nanoc/filters/rubypants.rb +14 -0
  75. data/lib/nanoc/filters/sass.rb +13 -0
  76. data/lib/nanoc/helpers/blogging.rb +170 -0
  77. data/lib/nanoc/helpers/capturing.rb +59 -0
  78. data/lib/nanoc/helpers/html_escape.rb +23 -0
  79. data/lib/nanoc/helpers/link_to.rb +69 -0
  80. data/lib/nanoc/helpers/render.rb +47 -0
  81. data/lib/nanoc/helpers/tagging.rb +52 -0
  82. data/lib/nanoc/helpers/xml_sitemap.rb +58 -0
  83. data/lib/nanoc/routers/default.rb +54 -0
  84. data/lib/nanoc/routers/no_dirs.rb +66 -0
  85. data/lib/nanoc/routers/versioned.rb +79 -0
  86. data/lib/nanoc.rb +83 -12
  87. metadata +144 -47
  88. data/lib/nanoc/base/auto_compiler.rb +0 -124
  89. data/lib/nanoc/base/layout_processor.rb +0 -33
  90. data/lib/nanoc/base/page_proxy.rb +0 -31
  91. data/lib/nanoc/base/plugin_manager.rb +0 -33
  92. data/lib/nanoc/data_sources/database.rb +0 -259
  93. data/lib/nanoc/data_sources/trivial.rb +0 -145
  94. data/lib/nanoc/filters/markdown.rb +0 -13
  95. data/lib/nanoc/filters/smartypants.rb +0 -13
  96. data/lib/nanoc/filters/textile.rb +0 -13
  97. data/lib/nanoc/layout_processors/erb.rb +0 -35
  98. data/lib/nanoc/layout_processors/haml.rb +0 -18
  99. data/lib/nanoc/layout_processors/markaby.rb +0 -16
@@ -1,33 +0,0 @@
1
- module Nanoc
2
- class PluginManager
3
-
4
- @@data_sources = {}
5
- @@filters = {}
6
- @@layout_processors = {}
7
-
8
- def self.subclasses_of(superclass)
9
- subclasses = []
10
- ObjectSpace.each_object(Class) { |subclass| subclasses << subclass if subclass < superclass }
11
- subclasses
12
- end
13
-
14
- def self.data_source_named(name)
15
- @@data_sources[name.to_sym] ||= subclasses_of(DataSource).find do |klass|
16
- klass.identifiers.include?(name.to_sym)
17
- end
18
- end
19
-
20
- def self.filter_named(name)
21
- @@filters[name.to_sym] ||= subclasses_of(Filter).find do |klass|
22
- klass.identifiers.include?(name.to_sym)
23
- end
24
- end
25
-
26
- def self.layout_processor_for_extension(ext)
27
- @@filters[ext.to_sym] ||= subclasses_of(LayoutProcessor).find do |klass|
28
- klass.extensions.include?(ext)
29
- end
30
- end
31
-
32
- end
33
- end
@@ -1,259 +0,0 @@
1
- begin ; require 'active_record' ; rescue LoadError ; end
2
-
3
- module Nanoc::DataSource::Database
4
-
5
- ########## Helper classes ##########
6
-
7
- begin
8
-
9
- class DatabasePage < ActiveRecord::Base
10
- set_table_name 'pages'
11
- end
12
-
13
- class DatabasePageDefault < ActiveRecord::Base
14
- set_table_name 'page_defaults'
15
- end
16
-
17
- class DatabaseTemplate < ActiveRecord::Base
18
- set_table_name 'templates'
19
- end
20
-
21
- class DatabaseLayout < ActiveRecord::Base
22
- set_table_name 'layouts'
23
- end
24
-
25
- class DatabaseCodePiece < ActiveRecord::Base
26
- set_table_name 'code_pieces'
27
- end
28
-
29
- rescue NameError
30
- end
31
-
32
- class DatabaseDataSource < Nanoc::DataSource
33
-
34
- ########## Attributes ##########
35
-
36
- identifier :database
37
-
38
- ########## Preparation ##########
39
-
40
- def up
41
- nanoc_require 'active_record'
42
-
43
- # Connect to the database
44
- ActiveRecord::Base.establish_connection(@site.config[:database])
45
- end
46
-
47
- def down
48
- # Disconnect from the database
49
- ActiveRecord::Base.remove_connection
50
- end
51
-
52
- def setup
53
- # Create tables
54
- schema = ActiveRecord::Schema
55
- schema.verbose = false
56
- schema.define do
57
-
58
- create_table :pages, :force => true do |t|
59
- t.column :content, :text
60
- t.column :path, :string
61
- t.column :meta, :text
62
- end
63
-
64
- create_table :page_defaults, :force => true do |t|
65
- t.column :meta, :text
66
- end
67
-
68
- create_table :layouts, :force => true do |t|
69
- t.column :name, :string
70
- t.column :content, :text
71
- t.column :extension, :string
72
- end
73
-
74
- create_table :templates, :force => true do |t|
75
- t.column :content, :text
76
- t.column :name, :string
77
- t.column :meta, :text
78
- end
79
-
80
- create_table :code_pieces, :force => true do |t|
81
- t.column :name, :string
82
- t.column :code, :text
83
- end
84
-
85
- end
86
-
87
- # Create first page
88
- DatabasePage.create(
89
- :path => '/',
90
- :content => "I'm a brand new root page. Please edit me!\n",
91
- :meta => "# Built-in\n" +
92
- "\n" +
93
- "# Custom\n" +
94
- "title: \"A New Root Page\"\n"
95
- )
96
-
97
- # Create page defaults
98
- DatabasePageDefault.create(
99
- :meta => "# Built-in\n" +
100
- "custom_path: none\n" +
101
- "extension: \"html\"\n" +
102
- "filename: \"index\"\n" +
103
- "filters_post: []\n" +
104
- "filters_pre: []\n" +
105
- "is_draft: false\n" +
106
- "layout: \"default\"\n" +
107
- "skip_output: false\n" +
108
- "\n" +
109
- "# Custom\n"
110
- )
111
-
112
- # Create default layout
113
- DatabaseLayout.create(
114
- :name => 'default',
115
- :content => "<html>\n" +
116
- " <head>\n" +
117
- " <title><%= @page.title %></title>\n" +
118
- " </head>\n" +
119
- " <body>\n" +
120
- "<%= @page.content %>\n" +
121
- " </body>\n" +
122
- "</html>",
123
- :extension => '.erb'
124
- )
125
-
126
- # Create default template
127
- DatabaseTemplate.create(
128
- :name => 'default',
129
- :content => 'Hi, I\'m a new page!',
130
- :meta => "# Built-in\n" +
131
- "\n" +
132
- "# Custom\n" +
133
- "title: \"A New Page\"\n"
134
- )
135
-
136
- # Create default code piece
137
- DatabaseCodePiece.create(
138
- :name => 'default',
139
- :code => "def html_escape(str)\n" +
140
- " str.gsub('&', '&amp;').str('<', '&lt;').str('>', '&gt;').str('\"', '&quot;')\n" +
141
- "end\n" +
142
- "alias h html_escape\n"
143
- )
144
-
145
- log(:high, "Set up database schema.")
146
- end
147
-
148
- ########## Loading data ##########
149
-
150
- def pages
151
- # Create Pages for each database object
152
- DatabasePage.find(:all).inject([]) do |pages, page|
153
- # Read metadata
154
- hash = (YAML.load(page.meta || '') || {}).clean
155
-
156
- if hash[:is_draft]
157
- # Skip drafts
158
- pages
159
- else
160
- # Get extra info
161
- extras = { :path => page.path, :uncompiled_content => page.content }
162
-
163
- # Add to list of pages
164
- pages + [ hash.merge(extras) ]
165
- end
166
- end
167
- end
168
-
169
- def page_defaults
170
- YAML.load(DatabasePageDefault.find(:first).meta) || {}
171
- end
172
-
173
- def layouts
174
- DatabaseLayout.find(:all).map do |layout|
175
- {
176
- :name => layout.name,
177
- :content => layout.content,
178
- :extension => layout.extension
179
- }
180
- end
181
- end
182
-
183
- def templates
184
- DatabaseTemplate.find(:all).map do |template|
185
- {
186
- :name => template.name,
187
- :content => template.content,
188
- :meta => template.meta
189
- }
190
- end
191
- end
192
-
193
- def code
194
- DatabaseCodePiece.find(:all).map { |p| p.code }.join("\n")
195
- end
196
-
197
- ########## Creating data ##########
198
-
199
- def create_page(path, template)
200
- # Make sure path does not start or end with a slash
201
- sanitized_path = ('/' + path + '/').gsub(/^\/+|\/+$/, '/')
202
-
203
- # Make sure the page doesn't exist yet
204
- unless DatabasePage.find_all_by_path(sanitized_path).empty?
205
- error "A page named '#{sanitized_path}' already exists."
206
- end
207
-
208
- # Create page
209
- DatabasePage.create(
210
- :path => sanitized_path,
211
- :content => "I'm a brand new page. Please edit me!\n",
212
- :meta => "# Built-in\n\n# Custom\ntitle: A New Page\n"
213
- )
214
-
215
- log(:high, "Created page '#{sanitized_path}'.")
216
- end
217
-
218
- def create_layout(name)
219
- # Make sure the layout doesn't exist yet
220
- unless DatabaseLayout.find_all_by_name(name).empty?
221
- error "A layout named '#{name}' already exists."
222
- end
223
-
224
- # Create layout
225
- DatabaseLayout.create(
226
- :name => name,
227
- :content => "<html>\n" +
228
- " <head>\n" +
229
- " <title><%= @page.title %></title>\n" +
230
- " </head>\n" +
231
- " <body>\n" +
232
- "<%= @page.content %>\n" +
233
- " </body>\n" +
234
- "</html>",
235
- :extension => '.erb'
236
- )
237
-
238
- log(:high, "Created layout '#{name}'.")
239
- end
240
-
241
- def create_template(name)
242
- # Make sure the layout doesn't exist yet
243
- unless DatabaseTemplate.find_all_by_name(name).empty?
244
- error "A template named '#{name}' already exists."
245
- end
246
-
247
- # Create template
248
- DatabaseTemplate.create(
249
- :name => name,
250
- :content => "Hi, I'm a brand new page!\n",
251
- :meta => "# Built-in\n\n# Custom\ntitle: A New Page\n"
252
- )
253
-
254
- log(:high,"Created template '#{name}'.")
255
- end
256
-
257
- end
258
-
259
- end
@@ -1,145 +0,0 @@
1
- # This is the module where the trivial data source will live in. It's not
2
- # really _necessary_ to create a separate module/namespace for each data
3
- # source, but it can be useful, especially when the data source needs extra
4
- # classes (for example, the database data source defines uses ActiveRecord, so
5
- # it needs classes for each table).
6
- module Nanoc::DataSource::Trivial
7
-
8
- # This is the implementation of a trivial data source. It doesn't do much
9
- # except return bogus data. It is meant to be a very simple example of a
10
- # data source, and it should be quite useful for those who want to write
11
- # their own data sources.
12
- class TrivialDataSource < Nanoc::DataSource
13
-
14
- ########## Attributes ##########
15
-
16
- # DataSource.identifier defines the name for this data source. The first
17
- # and only argument is the data source name as a symbol.
18
- identifier :trivial
19
-
20
- ########## Preparation ##########
21
-
22
- # DataSource#up is run before compiling. This is the place where you
23
- # should initialize the data source, if necessary. You don't need to
24
- # implement it; you can leave it out if you don't need initialization.
25
- # This is the ideal place to connect to the database, for example.
26
- # If your data source requires any special libraries, require them here
27
- # using 'nanoc_require'.
28
- def up
29
- end
30
-
31
- # DataSource#down is run after compiling. This is where you should clean
32
- # up any resources you used during the site compilation. You don't need to
33
- # implement it; you can leave it out if there's nothing to clean up. For
34
- # example, this is a good place to close the connection to the database,
35
- # if you have one.
36
- def down
37
- end
38
-
39
- # DataSource#setup is run when the site is created. This is the place
40
- # where you should create the data source for the first time. You don't
41
- # need to implement it; you can leave it out if there's nothing to set up.
42
- # For example, if you're using a database, this is where you should create
43
- # the necessary tables for the data source to function properly.
44
- def setup
45
- error "Sorry. The trivial data source isn't competent enough."
46
- end
47
-
48
- ########## Loading data ##########
49
-
50
- # DataSource#pages returns an array of hashes that represent pages. Each
51
- # hash must have at least the :uncompiled_content and :path keys. You can
52
- # include other metadata in this hash, though.
53
- def pages
54
- [
55
- { :uncompiled_content => 'Hi!', :path => '/' },
56
- { :uncompiled_content => 'Hello there.', :path => '/about/' }
57
- ]
58
- end
59
-
60
- # Datasource#page_defaults returns a hash with default values for page
61
- # metadata. This hash can be anything, even an empty hash if you wish.
62
- def page_defaults
63
- { :layout => 'quux' }
64
- end
65
-
66
- # DataSource#layouts returns an array of hashes that represent layouts.
67
- # Each hash must have the :name, :content and :extension keys. The
68
- # :extension key determines the layout processor that will be used (they
69
- # are defined in layout_processors/*.rb).
70
- def layouts
71
- [
72
- {
73
- :name => 'quux',
74
- :content => "<html>\n" +
75
- " <head>\n" +
76
- " <title><%= @page.title %></title>\n" +
77
- " </head>\n" +
78
- " <body>\n" +
79
- "<%= @page.content %>\n" +
80
- " </body>\n" +
81
- "</html>",
82
- :extension => '.erb'
83
- }
84
- ]
85
- end
86
-
87
- # DataSource#templates returns an array of hashes that represent page
88
- # templates. These page templates are used used by DataSource#create_page
89
- # to create pages using a template. Each hash must have the :name key for
90
- # identifying the template. Apart from that, you can structure the hash
91
- # like you desire. I recommend having :content (for the page content) and
92
- # :meta (for the page metadata) keys. Note that in this example, the value
93
- # corresponding to the :meta key is a hash, but it could just as well have
94
- # been a YAML-formatted string. Just make sure that what
95
- # DataSource#templates serves is what DataSource#create_page expects.
96
- def templates
97
- [
98
- {
99
- :name => 'default',
100
- :content => 'Hi, I am a new page. Please edit me!',
101
- :meta => { :title => 'A New Page' }
102
- }
103
- ]
104
- end
105
-
106
- # DataSource#code returns a string containing custom code which will be
107
- # loaded before the site is compiled. This can be code for custom filters
108
- # and layout processors, but pretty much any code can be put in there
109
- # (global helper functions are very useful). It is possible to override
110
- # methods of built-in nanoc classes, but doing so will likely cause
111
- # massive breakage, so doing so is not recommended.
112
- def code
113
- "def foo ; 'bar' ; end"
114
- end
115
-
116
- ########## Creating data ##########
117
-
118
- # DataSource#create_page is run when a page is created. This function
119
- # should create a new page with the given name and using the given
120
- # template. The template is a hash taken the array of hashes returned by
121
- # DataSource#templates, so make sure that what DataSource#templates
122
- # returns is what DataSource#create_page expects. This trivial data source
123
- # doesn't have a permanent storage, so it can't create any pages.
124
- def create_page(path, template)
125
- error "Sorry. The trivial data source isn't competent enough."
126
- end
127
-
128
- # DataSource#create_layout is run when a layout is created. This function
129
- # should create a new layout with the given name. This trivial data source
130
- # doesn't have a permanent storage, so it can't create any layouts.
131
- def create_layout(name)
132
- error "Sorry. The trivial data source isn't competent enough."
133
- end
134
-
135
- # DataSource#create_template is run when a template is created. This
136
- # function should create a new template with the given name. This trivial
137
- # data source doesn't have a permanent storage, so it can't create any
138
- # templates.
139
- def create_template(name)
140
- error "Sorry. The trivial data source isn't competent enough."
141
- end
142
-
143
- end
144
-
145
- end
@@ -1,13 +0,0 @@
1
- module Nanoc::Filter::Markdown
2
- class MarkdownFilter < Nanoc::Filter
3
-
4
- identifiers :markdown, :bluecloth
5
-
6
- def run(content)
7
- nanoc_require 'bluecloth'
8
-
9
- ::BlueCloth.new(content).to_html
10
- end
11
-
12
- end
13
- end
@@ -1,13 +0,0 @@
1
- module Nanoc::Filter::SmartyPants
2
- class SmartyPantsFilter < Nanoc::Filter
3
-
4
- identifiers :smartypants, :rubypants
5
-
6
- def run(content)
7
- nanoc_require 'rubypants'
8
-
9
- ::RubyPants.new(content).to_html
10
- end
11
-
12
- end
13
- end
@@ -1,13 +0,0 @@
1
- module Nanoc::Filter::Textile
2
- class TextileFilter < Nanoc::Filter
3
-
4
- identifiers :textile, :redcloth
5
-
6
- def run(content)
7
- nanoc_require 'redcloth'
8
-
9
- ::RedCloth.new(content).to_html
10
- end
11
-
12
- end
13
- end
@@ -1,35 +0,0 @@
1
- module Nanoc::LayoutProcessor::ERB
2
-
3
- class ERBContext
4
-
5
- def initialize(hash)
6
- hash.each_pair do |key, value|
7
- instance_variable_set('@' + key.to_s, value)
8
- end
9
- end
10
-
11
- def get_binding
12
- binding
13
- end
14
-
15
- end
16
-
17
- class ERBLayoutProcessor < Nanoc::LayoutProcessor
18
-
19
- identifiers :erb, :eruby
20
- extensions '.erb', '.rhtml'
21
-
22
- def run(layout)
23
- nanoc_require 'erb'
24
-
25
- # Create context
26
- assigns = @other_assigns.merge({ :page => @page, :pages => @pages, :config => @config, :site => @site })
27
- context = ERBContext.new(assigns)
28
-
29
- # Get result
30
- ::ERB.new(layout).result(context.get_binding)
31
- end
32
-
33
- end
34
-
35
- end
@@ -1,18 +0,0 @@
1
- module Nanoc::LayoutProcessor::Haml
2
- class HamlLayoutProcessor < Nanoc::LayoutProcessor
3
-
4
- identifiers :haml
5
- extensions '.haml'
6
-
7
- def run(layout)
8
- nanoc_require 'haml'
9
-
10
- options = @page[:haml_options] || {}
11
- assigns = @other_assigns.merge({ :page => @page, :pages => @pages, :config => @config, :site => @site })
12
- options[:locals] = assigns
13
-
14
- ::Haml::Engine.new(layout, options).to_html
15
- end
16
-
17
- end
18
- end
@@ -1,16 +0,0 @@
1
- module Nanoc::LayoutProcessor::Markaby
2
- class MarkabyLayoutProcessor < Nanoc::LayoutProcessor
3
-
4
- identifiers :markaby
5
- extensions '.mab'
6
-
7
- def run(layout)
8
- nanoc_require 'markaby'
9
-
10
- assigns = @other_assigns.merge({ :page => @page, :pages => @pages, :config => @config, :site => @site })
11
-
12
- ::Markaby::Builder.new(assigns).instance_eval(layout).to_s
13
- end
14
-
15
- end
16
- end