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.
- data/ChangeLog +54 -0
- data/LICENSE +1 -1
- data/README +63 -3
- data/Rakefile +61 -14
- data/bin/nanoc +7 -199
- data/lib/nanoc/base/asset.rb +113 -0
- data/lib/nanoc/base/asset_defaults.rb +21 -0
- data/lib/nanoc/base/asset_rep.rb +277 -0
- data/lib/nanoc/base/binary_filter.rb +44 -0
- data/lib/nanoc/base/code.rb +41 -0
- data/lib/nanoc/base/compiler.rb +46 -34
- data/lib/nanoc/base/core_ext/hash.rb +51 -7
- data/lib/nanoc/base/core_ext/string.rb +8 -0
- data/lib/nanoc/base/data_source.rb +253 -20
- data/lib/nanoc/base/defaults.rb +30 -0
- data/lib/nanoc/base/enhancements.rb +9 -84
- data/lib/nanoc/base/filter.rb +109 -6
- data/lib/nanoc/base/layout.rb +91 -0
- data/lib/nanoc/base/notification_center.rb +66 -0
- data/lib/nanoc/base/page.rb +94 -121
- data/lib/nanoc/base/page_defaults.rb +20 -0
- data/lib/nanoc/base/page_rep.rb +318 -0
- data/lib/nanoc/base/plugin.rb +57 -9
- data/lib/nanoc/base/proxies/asset_proxy.rb +29 -0
- data/lib/nanoc/base/proxies/asset_rep_proxy.rb +26 -0
- data/lib/nanoc/base/proxies/layout_proxy.rb +25 -0
- data/lib/nanoc/base/proxies/page_proxy.rb +35 -0
- data/lib/nanoc/base/proxies/page_rep_proxy.rb +28 -0
- data/lib/nanoc/base/proxy.rb +37 -0
- data/lib/nanoc/base/router.rb +72 -0
- data/lib/nanoc/base/site.rb +220 -91
- data/lib/nanoc/base/template.rb +64 -0
- data/lib/nanoc/binary_filters/image_science_thumbnail.rb +28 -0
- data/lib/nanoc/cli/base.rb +219 -0
- data/lib/nanoc/cli/cli.rb +16 -0
- data/lib/nanoc/cli/command.rb +105 -0
- data/lib/nanoc/cli/commands/autocompile.rb +80 -0
- data/lib/nanoc/cli/commands/compile.rb +273 -0
- data/lib/nanoc/cli/commands/create_layout.rb +85 -0
- data/lib/nanoc/cli/commands/create_page.rb +85 -0
- data/lib/nanoc/cli/commands/create_site.rb +327 -0
- data/lib/nanoc/cli/commands/create_template.rb +76 -0
- data/lib/nanoc/cli/commands/help.rb +69 -0
- data/lib/nanoc/cli/commands/info.rb +114 -0
- data/lib/nanoc/cli/commands/switch.rb +141 -0
- data/lib/nanoc/cli/commands/update.rb +91 -0
- data/lib/nanoc/cli/ext.rb +37 -0
- data/lib/nanoc/cli/logger.rb +66 -0
- data/lib/nanoc/cli/option_parser.rb +168 -0
- data/lib/nanoc/cli.rb +1 -0
- data/lib/nanoc/data_sources/filesystem.rb +650 -215
- data/lib/nanoc/data_sources/filesystem_combined.rb +495 -0
- data/lib/nanoc/extra/auto_compiler.rb +265 -0
- data/lib/nanoc/extra/context.rb +22 -0
- data/lib/nanoc/extra/core_ext/hash.rb +54 -0
- data/lib/nanoc/extra/core_ext/time.rb +13 -0
- data/lib/nanoc/extra/file_proxy.rb +29 -0
- data/lib/nanoc/extra/vcs.rb +48 -0
- data/lib/nanoc/extra/vcses/bazaar.rb +21 -0
- data/lib/nanoc/extra/vcses/dummy.rb +20 -0
- data/lib/nanoc/extra/vcses/git.rb +21 -0
- data/lib/nanoc/extra/vcses/mercurial.rb +21 -0
- data/lib/nanoc/extra/vcses/subversion.rb +21 -0
- data/lib/nanoc/filters/bluecloth.rb +13 -0
- data/lib/nanoc/filters/erb.rb +6 -22
- data/lib/nanoc/filters/erubis.rb +14 -0
- data/lib/nanoc/filters/haml.rb +11 -6
- data/lib/nanoc/filters/markaby.rb +5 -5
- data/lib/nanoc/filters/maruku.rb +14 -0
- data/lib/nanoc/filters/old.rb +19 -0
- data/lib/nanoc/filters/rdiscount.rb +13 -0
- data/lib/nanoc/filters/rdoc.rb +5 -4
- data/lib/nanoc/filters/redcloth.rb +14 -0
- data/lib/nanoc/filters/rubypants.rb +14 -0
- data/lib/nanoc/filters/sass.rb +13 -0
- data/lib/nanoc/helpers/blogging.rb +170 -0
- data/lib/nanoc/helpers/capturing.rb +59 -0
- data/lib/nanoc/helpers/html_escape.rb +23 -0
- data/lib/nanoc/helpers/link_to.rb +69 -0
- data/lib/nanoc/helpers/render.rb +47 -0
- data/lib/nanoc/helpers/tagging.rb +52 -0
- data/lib/nanoc/helpers/xml_sitemap.rb +58 -0
- data/lib/nanoc/routers/default.rb +54 -0
- data/lib/nanoc/routers/no_dirs.rb +66 -0
- data/lib/nanoc/routers/versioned.rb +79 -0
- data/lib/nanoc.rb +83 -12
- metadata +144 -47
- data/lib/nanoc/base/auto_compiler.rb +0 -124
- data/lib/nanoc/base/layout_processor.rb +0 -33
- data/lib/nanoc/base/page_proxy.rb +0 -31
- data/lib/nanoc/base/plugin_manager.rb +0 -33
- data/lib/nanoc/data_sources/database.rb +0 -259
- data/lib/nanoc/data_sources/trivial.rb +0 -145
- data/lib/nanoc/filters/markdown.rb +0 -13
- data/lib/nanoc/filters/smartypants.rb +0 -13
- data/lib/nanoc/filters/textile.rb +0 -13
- data/lib/nanoc/layout_processors/erb.rb +0 -35
- data/lib/nanoc/layout_processors/haml.rb +0 -18
- data/lib/nanoc/layout_processors/markaby.rb +0 -16
|
@@ -1,15 +1,31 @@
|
|
|
1
1
|
module Nanoc
|
|
2
|
-
class DataSource < Plugin
|
|
3
2
|
|
|
4
|
-
|
|
3
|
+
# Nanoc::DataSource is responsible for loading data. It is the (abstract)
|
|
4
|
+
# superclass for all data sources. Subclasses must at least implement the
|
|
5
|
+
# data reading methods (+pages+, +page_defaults+, +layouts+, +templates+,
|
|
6
|
+
# and +code+); all other methods involving data manipulation are optional.
|
|
7
|
+
#
|
|
8
|
+
# Apart from the methods for loading and storing data, there are the +up+
|
|
9
|
+
# and +down+ methods for bringing up and tearing down the connection to the
|
|
10
|
+
# data source. These should be overridden in subclasses. The +loading+
|
|
11
|
+
# method wraps +up+ and +down+.
|
|
12
|
+
#
|
|
13
|
+
# The +setup+ method is used for setting up a site's data source for the
|
|
14
|
+
# first time. This method should be overridden in subclasses.
|
|
15
|
+
class DataSource < Plugin
|
|
5
16
|
|
|
17
|
+
# Creates a new data source for the given site.
|
|
6
18
|
def initialize(site)
|
|
7
19
|
@site = site
|
|
8
20
|
@references = 0
|
|
9
21
|
end
|
|
10
22
|
|
|
11
|
-
#
|
|
12
|
-
|
|
23
|
+
# Loads the data source when necessary (calling +up+), yields, and unloads
|
|
24
|
+
# the data source when it is not being used elsewhere. All data source
|
|
25
|
+
# queries and data manipulations should be wrapped in a +loading+ block;
|
|
26
|
+
# it ensures that the data source is loaded when necessary and makes sure
|
|
27
|
+
# the data source does not get unloaded while it is still being used
|
|
28
|
+
# elsewhere.
|
|
13
29
|
def loading
|
|
14
30
|
# Load if necessary
|
|
15
31
|
up if @references == 0
|
|
@@ -22,31 +38,248 @@ module Nanoc
|
|
|
22
38
|
down if @references == 0
|
|
23
39
|
end
|
|
24
40
|
|
|
25
|
-
|
|
26
|
-
|
|
41
|
+
########## Loading and unloading
|
|
42
|
+
|
|
43
|
+
# Brings up the connection to the data. This is an abstract method
|
|
44
|
+
# implemented by the subclass. Depending on the way data is stored, this
|
|
45
|
+
# may not be necessary. This is the ideal place to connect to the
|
|
46
|
+
# database, for example.
|
|
47
|
+
#
|
|
48
|
+
# Subclasses may implement this method.
|
|
49
|
+
def up
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Brings down the connection to the data. This is an abstract method
|
|
53
|
+
# implemented by the subclass. This method should undo the effects of
|
|
54
|
+
# +up+.
|
|
55
|
+
#
|
|
56
|
+
# Subclasses may implement this method.
|
|
57
|
+
def down
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
########## Creating/updating
|
|
61
|
+
|
|
62
|
+
# Creates the bare minimum essentials for this data source to work. This
|
|
63
|
+
# action will likely be destructive. This method should not create sample
|
|
64
|
+
# data such as a default home page, a default layout, etc. For example, if
|
|
65
|
+
# you're using a database, this is where you should create the necessary
|
|
66
|
+
# tables for the data source to function properly.
|
|
67
|
+
#
|
|
68
|
+
# Subclasses must implement this method.
|
|
69
|
+
def setup
|
|
70
|
+
not_implemented('setup')
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Removes all data stored by this data source. This method undoes the
|
|
74
|
+
# effects of the +setup+ method.
|
|
75
|
+
#
|
|
76
|
+
# Subclasses must implement this method.
|
|
77
|
+
def destroy
|
|
78
|
+
not_implemented('destroy')
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Updated the content stored in this site to a newer version. A newer
|
|
82
|
+
# version of a data source may store content in a different format, and
|
|
83
|
+
# this method will update the stored content to this newer format.
|
|
84
|
+
#
|
|
85
|
+
# Subclasses may implement this method.
|
|
86
|
+
def update
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
########## Pages
|
|
90
|
+
|
|
91
|
+
# Returns the list of pages (represented by Nanoc::Page) in this site.
|
|
92
|
+
# This is an abstract method implemented by the subclass.
|
|
93
|
+
#
|
|
94
|
+
# Subclasses must implement this method.
|
|
95
|
+
def pages
|
|
96
|
+
not_implemented('pages')
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Saves the given page in the data source, creating it if it doesn't exist
|
|
100
|
+
# yet and updating the existing copy otherwise.
|
|
101
|
+
#
|
|
102
|
+
# Subclasses must implement this method.
|
|
103
|
+
def save_page(page)
|
|
104
|
+
not_implemented('save_page')
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Changes the path of the given page to the given new path. When changing
|
|
108
|
+
# a page's path, this method must be used (save_page will not work).
|
|
109
|
+
#
|
|
110
|
+
# Subclasses must implement this method.
|
|
111
|
+
def move_page(page, new_path)
|
|
112
|
+
not_implemented('move_page')
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Removes the given page from the data source.
|
|
116
|
+
#
|
|
117
|
+
# Subclasses must implement this method.
|
|
118
|
+
def delete_page(page)
|
|
119
|
+
not_implemented('delete_page')
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
########## Assets
|
|
123
|
+
|
|
124
|
+
# Returns the list of assets (represented by Nanoc::Asset) in this site.
|
|
125
|
+
# This is an abstract method implemented by the subclass.
|
|
126
|
+
#
|
|
127
|
+
# Subclasses must implement this method.
|
|
128
|
+
def assets
|
|
129
|
+
not_implemented('assets')
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Saves the given asset in the data source, creating it if it doesn't
|
|
133
|
+
# exist yet and updating the existing copy otherwise.
|
|
134
|
+
#
|
|
135
|
+
# Subclasses must implement this method.
|
|
136
|
+
def save_asset(asset)
|
|
137
|
+
not_implemented('save_asset')
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# Changes the path of the given asset to the given new path. When changing
|
|
141
|
+
# a asset's path, this method must be used (save_asset will not work).
|
|
142
|
+
#
|
|
143
|
+
# Subclasses must implement this method.
|
|
144
|
+
def move_asset(asset, new_path)
|
|
145
|
+
not_implemented('move_asset')
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# Removes the given asset from the data source.
|
|
149
|
+
#
|
|
150
|
+
# Subclasses must implement this method.
|
|
151
|
+
def delete_asset(asset)
|
|
152
|
+
not_implemented('delete_asset')
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
########## Page defaults
|
|
27
156
|
|
|
28
|
-
|
|
157
|
+
# Returns the page defaults (represented by Nanoc::PageDefaults) of this
|
|
158
|
+
# site. This is an abstract method implemented by the subclass.
|
|
159
|
+
#
|
|
160
|
+
# Subclasses must implement this method.
|
|
161
|
+
def page_defaults
|
|
162
|
+
not_implemented('page_defaults')
|
|
163
|
+
end
|
|
29
164
|
|
|
30
|
-
#
|
|
165
|
+
# Saves the given page defaults in the data source.
|
|
166
|
+
#
|
|
167
|
+
# Subclasses must implement this method.
|
|
168
|
+
def save_page_defaults(page_defaults)
|
|
169
|
+
not_implemented('save_page_defaults')
|
|
170
|
+
end
|
|
31
171
|
|
|
32
|
-
|
|
33
|
-
def page_defaults ; error 'DataSource#page_defaults must be overridden' ; end
|
|
34
|
-
def layouts ; error 'DataSource#layouts must be overridden' ; end
|
|
35
|
-
def templates ; error 'DataSource#templates must be overridden' ; end
|
|
36
|
-
def code ; error 'DataSource#code must be overridden' ; end
|
|
172
|
+
########## Asset defaults
|
|
37
173
|
|
|
38
|
-
#
|
|
174
|
+
# Returns the asset defaults (represented by Nanoc::AssetDefaults) of this
|
|
175
|
+
# site. This is an abstract method implemented by the subclass.
|
|
176
|
+
#
|
|
177
|
+
# Subclasses must implement this method.
|
|
178
|
+
def asset_defaults
|
|
179
|
+
not_implemented('asset_defaults')
|
|
180
|
+
end
|
|
39
181
|
|
|
40
|
-
|
|
41
|
-
|
|
182
|
+
# Saves the given asset defaults in the data source.
|
|
183
|
+
#
|
|
184
|
+
# Subclasses must implement this method.
|
|
185
|
+
def save_asset_defaults(asset_defaults)
|
|
186
|
+
not_implemented('save_asset_defaults')
|
|
42
187
|
end
|
|
43
188
|
|
|
44
|
-
|
|
45
|
-
|
|
189
|
+
########## Layouts
|
|
190
|
+
|
|
191
|
+
# Returns the list of layouts (represented by Nanoc::Layout) in this site.
|
|
192
|
+
# This is an abstract method implemented by the subclass.
|
|
193
|
+
#
|
|
194
|
+
# Subclasses must implement this method.
|
|
195
|
+
def layouts
|
|
196
|
+
not_implemented('layouts')
|
|
46
197
|
end
|
|
47
198
|
|
|
48
|
-
|
|
49
|
-
|
|
199
|
+
# Saves the given layout in the data source, creating it if it doesn't
|
|
200
|
+
# exist yet and updating the existing copy otherwise.
|
|
201
|
+
#
|
|
202
|
+
# Subclasses must implement this method.
|
|
203
|
+
def save_layout(layout)
|
|
204
|
+
not_implemented('save_layout')
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# Changes the path of the given layout to the given new path. When
|
|
208
|
+
# changing a layout's path, this method must be used (save_layout will not
|
|
209
|
+
# work).
|
|
210
|
+
#
|
|
211
|
+
# Subclasses must implement this method.
|
|
212
|
+
def move_layout(layout, new_path)
|
|
213
|
+
not_implemented('move_layout')
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
# Removes the given layout from the data source.
|
|
217
|
+
#
|
|
218
|
+
# Subclasses must implement this method.
|
|
219
|
+
def delete_layout(layout)
|
|
220
|
+
not_implemented('delete_layout')
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
########## Templates
|
|
224
|
+
|
|
225
|
+
# Returns the list of templates (represented by Nanoc::Template) in this
|
|
226
|
+
# site. This is an abstract method implemented by the subclass.
|
|
227
|
+
#
|
|
228
|
+
# Subclasses must implement this method.
|
|
229
|
+
def templates
|
|
230
|
+
not_implemented('templates')
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
# Saves the given template in the data source, creating it if it doesn't
|
|
234
|
+
# exist yet and updating the existing copy otherwise.
|
|
235
|
+
#
|
|
236
|
+
# Subclasses must implement this method.
|
|
237
|
+
def save_template(template)
|
|
238
|
+
not_implemented('save_template')
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
# Changes the name of the given template to the given new name. When
|
|
242
|
+
# changing a template's name, this method must be used (save_template will
|
|
243
|
+
# not work).
|
|
244
|
+
#
|
|
245
|
+
# Subclasses must implement this method.
|
|
246
|
+
def move_template(template, new_name)
|
|
247
|
+
not_implemented('move_template')
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
# Removes the given template from the data source.
|
|
251
|
+
#
|
|
252
|
+
# Subclasses must implement this method.
|
|
253
|
+
def delete_template(template)
|
|
254
|
+
not_implemented('delete_template')
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
########## Code
|
|
258
|
+
|
|
259
|
+
# Returns the custom code (represented by Nanoc::Code) for this site.
|
|
260
|
+
# This is an abstract method implemented by the subclass. This can be code
|
|
261
|
+
# for custom filters, routers, and more, but pretty much any code can
|
|
262
|
+
# be put in there (global helper functions are very useful).
|
|
263
|
+
#
|
|
264
|
+
# Subclasses must implement this method.
|
|
265
|
+
def code
|
|
266
|
+
not_implemented('code')
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
# Saves the given code in the data source.
|
|
270
|
+
#
|
|
271
|
+
# Subclasses must implement this method.
|
|
272
|
+
def save_code(code)
|
|
273
|
+
not_implemented('save_code')
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
private
|
|
277
|
+
|
|
278
|
+
def not_implemented(name)
|
|
279
|
+
raise NotImplementedError.new(
|
|
280
|
+
"#{self.class} does not override ##{name}, which is required for " +
|
|
281
|
+
"this data source to be used."
|
|
282
|
+
)
|
|
50
283
|
end
|
|
51
284
|
|
|
52
285
|
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module Nanoc
|
|
2
|
+
|
|
3
|
+
# Nanoc::Defaults represent the default attributes for a given set of
|
|
4
|
+
# objects in the site. It is basically a hash with an optional modification
|
|
5
|
+
# time.
|
|
6
|
+
class Defaults
|
|
7
|
+
|
|
8
|
+
# Th site where this set of defaults belongs to.
|
|
9
|
+
attr_accessor :site
|
|
10
|
+
|
|
11
|
+
# A hash containing the default attributes.
|
|
12
|
+
attr_reader :attributes
|
|
13
|
+
|
|
14
|
+
# The time when this set of defaults was last modified.
|
|
15
|
+
attr_reader :mtime
|
|
16
|
+
|
|
17
|
+
# Creates a new set of defaults.
|
|
18
|
+
#
|
|
19
|
+
# +attributes+:: The hash containing the metadata that individual objects
|
|
20
|
+
# will override.
|
|
21
|
+
#
|
|
22
|
+
# +mtime+:: The time when the defaults were last modified (optional).
|
|
23
|
+
def initialize(attributes, mtime=nil)
|
|
24
|
+
@attributes = attributes.clean
|
|
25
|
+
@mtime = mtime
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
end
|
|
@@ -1,89 +1,14 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
require 'fileutils'
|
|
5
|
-
|
|
6
|
-
# Logging (level can be :off, :high, :low)
|
|
7
|
-
$log_level = :high
|
|
8
|
-
def log(log_level, s, io=$stdout)
|
|
9
|
-
io.puts s if ($log_level == :low or $log_level == log_level) and $log_level != :off
|
|
1
|
+
# Convenience function for printing warnings
|
|
2
|
+
def warn(s, pre='WARNING')
|
|
3
|
+
$stderr.puts "#{pre}: #{s}"
|
|
10
4
|
end
|
|
11
5
|
|
|
12
|
-
|
|
13
|
-
def error(s, pre='ERROR')
|
|
14
|
-
log(:high, pre + ': ' + s, $stderr)
|
|
15
|
-
exit(1)
|
|
16
|
-
end
|
|
6
|
+
############################# OLD AND DEPRECATED #############################
|
|
17
7
|
|
|
18
|
-
|
|
19
|
-
|
|
8
|
+
def nanoc_require(x)
|
|
9
|
+
warn(
|
|
10
|
+
"'nanoc_require' is deprecated and will be removed in a future version. Please use 'require' instead.",
|
|
11
|
+
'DEPRECATION WARNING'
|
|
12
|
+
)
|
|
20
13
|
require x
|
|
21
|
-
rescue LoadError
|
|
22
|
-
error(message)
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
# Rendering sub-layouts
|
|
26
|
-
def render(name, other_assigns={})
|
|
27
|
-
layout = @site.layouts.find { |l| l[:name] == name }
|
|
28
|
-
layout_processor_class = Nanoc::PluginManager.layout_processor_for_extension(layout[:extension])
|
|
29
|
-
layout_processor = layout_processor_class.new(@page, @pages, @site.config, @site, other_assigns)
|
|
30
|
-
layout_processor.run(layout[:content])
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
# Convenience function for cd'ing in and out of a directory
|
|
34
|
-
def in_dir(path)
|
|
35
|
-
FileUtils.cd(File.join(path))
|
|
36
|
-
yield
|
|
37
|
-
ensure
|
|
38
|
-
FileUtils.cd(File.join(path.map { |n| '..' }))
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
class FileManager
|
|
42
|
-
|
|
43
|
-
ACTION_COLORS = {
|
|
44
|
-
:create => "\e[1m" + "\e[32m", # bold + green
|
|
45
|
-
:update => "\e[1m" + "\e[33m", # bold + yellow
|
|
46
|
-
:identical => "\e[1m" # bold
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
def self.file_log(log_level, action, path)
|
|
50
|
-
log(log_level, '%s%12s%s %s' % [ACTION_COLORS[action.to_sym], action, "\e[0m", path])
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
def self.create_dir(name)
|
|
54
|
-
# Check whether directory exists
|
|
55
|
-
return if File.exist?(name)
|
|
56
|
-
|
|
57
|
-
# Create dir
|
|
58
|
-
FileUtils.mkdir_p(name)
|
|
59
|
-
log(:create, name)
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def self.create_file(path)
|
|
63
|
-
# Create parent directory if necessary
|
|
64
|
-
if path =~ /\//
|
|
65
|
-
parent_path = path.sub(/\/[^\/]+$/, '')
|
|
66
|
-
FileManager.create_dir(parent_path)
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
# Get contents
|
|
70
|
-
content_old = File.exist?(path) ? File.read(path) : nil
|
|
71
|
-
content_new = yield
|
|
72
|
-
content_new = content_new.force_encoding(content_old.encoding) if content_old and String.method_defined?(:force_encoding)
|
|
73
|
-
modified = (content_old != content_new)
|
|
74
|
-
|
|
75
|
-
# Log
|
|
76
|
-
if File.exist?(path)
|
|
77
|
-
file_log(*(modified ? [ :high, :update, path ] : [ :low, :identical, path ]))
|
|
78
|
-
else
|
|
79
|
-
file_log(:high, :create, path)
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
# Write
|
|
83
|
-
open(path, 'w') { |io| io.write(content_new) }
|
|
84
|
-
|
|
85
|
-
# Report back
|
|
86
|
-
modified
|
|
87
|
-
end
|
|
88
|
-
|
|
89
14
|
end
|
data/lib/nanoc/base/filter.rb
CHANGED
|
@@ -1,16 +1,119 @@
|
|
|
1
1
|
module Nanoc
|
|
2
|
+
|
|
3
|
+
# Nanoc::Filter is responsible for filtering pages and textual assets
|
|
4
|
+
# (binary assets are filtered using Nanoc::BinaryFilter). It is the
|
|
5
|
+
# (abstract) superclass for all textual filters. Subclasses should override
|
|
6
|
+
# the +run+ method.
|
|
2
7
|
class Filter < Plugin
|
|
3
8
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
+
# Deprecated
|
|
10
|
+
EXTENSIONS_MAP = {}
|
|
11
|
+
|
|
12
|
+
# Creates a new filter for the given object (page or asset) and site.
|
|
13
|
+
#
|
|
14
|
+
# +kind+:: The kind of object that is passed. Can be either +:page+ or
|
|
15
|
+
# +:asset+.
|
|
16
|
+
#
|
|
17
|
+
# +obj_rep+:: A proxy for the page or asset representation (Nanoc::PageRep
|
|
18
|
+
# or Nanoc::AssetRep) that should be compiled by this filter.
|
|
19
|
+
#
|
|
20
|
+
# +obj+:: A proxy for the page or asset's page (Nanoc::Page or
|
|
21
|
+
# Nanoc::Asset).
|
|
22
|
+
#
|
|
23
|
+
# +site+:: The site (Nanoc::Site) this filter belongs to.
|
|
24
|
+
#
|
|
25
|
+
# +other_assigns+:: A hash containing other variables that should be made
|
|
26
|
+
# available during filtering.
|
|
27
|
+
def initialize(obj_rep, other_assigns={})
|
|
28
|
+
# Determine kind
|
|
29
|
+
@kind = obj_rep.is_a?(Nanoc::PageRep) ? :page : :asset
|
|
30
|
+
|
|
31
|
+
# Set object
|
|
32
|
+
@obj_rep = obj_rep
|
|
33
|
+
@obj = (@kind == :page ? @obj_rep.page : @obj_rep.asset)
|
|
34
|
+
|
|
35
|
+
# Set page/asset and page/asset reps
|
|
36
|
+
if @kind == :page
|
|
37
|
+
@page = @obj
|
|
38
|
+
@page_rep = @obj_rep
|
|
39
|
+
else
|
|
40
|
+
@asset = @obj
|
|
41
|
+
@asset_rep = @obj_rep
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Set site
|
|
45
|
+
@site = @obj.site
|
|
46
|
+
|
|
47
|
+
# Set other assigns
|
|
48
|
+
@other_assigns = other_assigns
|
|
9
49
|
end
|
|
10
50
|
|
|
51
|
+
# Runs the filter. This method returns the filtered content.
|
|
52
|
+
#
|
|
53
|
+
# +content+:: The unprocessed content that should be filtered.
|
|
54
|
+
#
|
|
55
|
+
# Subclasses must implement this method.
|
|
11
56
|
def run(content)
|
|
12
|
-
|
|
57
|
+
raise NotImplementedError.new("Nanoc::Filter subclasses must implement #run")
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Returns a hash with data that should be available.
|
|
61
|
+
def assigns
|
|
62
|
+
@assigns ||= @other_assigns.merge({
|
|
63
|
+
:_obj_rep => @obj_rep,
|
|
64
|
+
:_obj => @obj,
|
|
65
|
+
:page_rep => @kind == :page ? @page_rep.to_proxy : nil,
|
|
66
|
+
:page => @kind == :page ? @page.to_proxy : nil,
|
|
67
|
+
:asset_rep => @kind == :asset ? @asset_rep.to_proxy : nil,
|
|
68
|
+
:asset => @kind == :asset ? @asset.to_proxy : nil,
|
|
69
|
+
:pages => @site.pages.map { |obj| obj.to_proxy },
|
|
70
|
+
:assets => @site.assets.map { |obj| obj.to_proxy },
|
|
71
|
+
:layouts => @site.layouts.map { |obj| obj.to_proxy },
|
|
72
|
+
:config => @site.config,
|
|
73
|
+
:site => @site
|
|
74
|
+
})
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
class << self
|
|
78
|
+
|
|
79
|
+
# Deprecated
|
|
80
|
+
def extensions(*extensions) # :nodoc:
|
|
81
|
+
# Initialize
|
|
82
|
+
@extensions = [] unless instance_variables.include?('@extensions')
|
|
83
|
+
|
|
84
|
+
if extensions.empty?
|
|
85
|
+
@extensions
|
|
86
|
+
else
|
|
87
|
+
@extensions = extensions
|
|
88
|
+
@extensions.each { |e| register_extension(e, self) }
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Deprecated
|
|
93
|
+
def extension(extension=nil) # :nodoc:
|
|
94
|
+
# Initialize
|
|
95
|
+
@extensions = [] unless instance_variables.include?('@extensions')
|
|
96
|
+
|
|
97
|
+
if extension.nil?
|
|
98
|
+
@extensions.first
|
|
99
|
+
else
|
|
100
|
+
@extensions = [ extension ]
|
|
101
|
+
register_extension(extension, self)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Deprecated
|
|
106
|
+
def register_extension(extension, klass)
|
|
107
|
+
EXTENSIONS_MAP[extension] = klass
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Deprecated
|
|
111
|
+
def with_extension(extension)
|
|
112
|
+
EXTENSIONS_MAP[extension]
|
|
113
|
+
end
|
|
114
|
+
|
|
13
115
|
end
|
|
14
116
|
|
|
15
117
|
end
|
|
118
|
+
|
|
16
119
|
end
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
module Nanoc
|
|
2
|
+
|
|
3
|
+
# A Nanoc::Layout represents a layout in a nanoc site. It has content,
|
|
4
|
+
# attributes (for determining which filter to use for laying out a page), a
|
|
5
|
+
# path (because layouts are organised hierarchically), and a modification
|
|
6
|
+
# time (to speed up compilation).
|
|
7
|
+
class Layout
|
|
8
|
+
|
|
9
|
+
# Default values for layouts.
|
|
10
|
+
DEFAULTS = {
|
|
11
|
+
:filter => 'erb'
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
# The Nanoc::Site this layout belongs to.
|
|
15
|
+
attr_accessor :site
|
|
16
|
+
|
|
17
|
+
# The raw content of this layout.
|
|
18
|
+
attr_reader :content
|
|
19
|
+
|
|
20
|
+
# A hash containing this layout's attributes.
|
|
21
|
+
attr_reader :attributes
|
|
22
|
+
|
|
23
|
+
# This layout's path, starting and ending with a slash.
|
|
24
|
+
attr_reader :path
|
|
25
|
+
|
|
26
|
+
# The time when this layout was last modified.
|
|
27
|
+
attr_reader :mtime
|
|
28
|
+
|
|
29
|
+
# Creates a new layout.
|
|
30
|
+
#
|
|
31
|
+
# +content+:: The raw content of this layout.
|
|
32
|
+
#
|
|
33
|
+
# +attributes+:: A hash containing this layout's attributes.
|
|
34
|
+
#
|
|
35
|
+
# +path+:: This layout's path, starting and ending with a slash.
|
|
36
|
+
#
|
|
37
|
+
# +mtime+:: The time when this layout was last modified.
|
|
38
|
+
def initialize(content, attributes, path, mtime=nil)
|
|
39
|
+
@content = content
|
|
40
|
+
@attributes = attributes.clean
|
|
41
|
+
@path = path.cleaned_path
|
|
42
|
+
@mtime = mtime
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Returns a proxy (Nanoc::LayoutProxy) for this layout.
|
|
46
|
+
def to_proxy
|
|
47
|
+
@proxy ||= LayoutProxy.new(self)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Returns the attribute with the given name.
|
|
51
|
+
def attribute_named(name)
|
|
52
|
+
return @attributes[name] if @attributes.has_key?(name)
|
|
53
|
+
return DEFAULTS[name]
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Returns the filter class needed for this layout.
|
|
57
|
+
def filter_class
|
|
58
|
+
if attribute_named(:extension).nil?
|
|
59
|
+
Nanoc::Filter.named(attribute_named(:filter))
|
|
60
|
+
else
|
|
61
|
+
Nanoc::Filter.with_extension(attribute_named(:extension))
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Saves the layout in the database, creating it if it doesn't exist yet or
|
|
66
|
+
# updating it if it already exists. Tells the site's data source to save
|
|
67
|
+
# the layout.
|
|
68
|
+
def save
|
|
69
|
+
@site.data_source.loading do
|
|
70
|
+
@site.data_source.save_layout(self)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Moves the layout to a new path. Tells the site's data source to move the
|
|
75
|
+
# layout.
|
|
76
|
+
def move_to(new_path)
|
|
77
|
+
@site.data_source.loading do
|
|
78
|
+
@site.data_source.move_layout(self, new_path)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Deletes the layout. Tells the site's data source to delete the layout.
|
|
83
|
+
def delete
|
|
84
|
+
@site.data_source.loading do
|
|
85
|
+
@site.data_source.delete_layout(self)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
end
|