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,262 +1,586 @@
|
|
|
1
|
-
module Nanoc::
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
module Nanoc::DataSources
|
|
2
|
+
|
|
3
|
+
# The filesystem data source is the default data source for a new nanoc
|
|
4
|
+
# site. It stores all data as files on the hard disk.
|
|
5
|
+
#
|
|
6
|
+
# None of the methods are documented in this file. See Nanoc::DataSource for
|
|
7
|
+
# documentation on the overridden methods instead.
|
|
8
|
+
#
|
|
9
|
+
# = Pages
|
|
10
|
+
#
|
|
11
|
+
# The filesystem data source stores its pages in nested directories. Each
|
|
12
|
+
# directory represents a single page. The root directory is the 'content'
|
|
13
|
+
# directory.
|
|
14
|
+
#
|
|
15
|
+
# Every directory has a content file and a meta file. The content file
|
|
16
|
+
# contains the actual page content, while the meta file contains the page's
|
|
17
|
+
# metadata, formatted as YAML.
|
|
18
|
+
#
|
|
19
|
+
# Both content files and meta files are named after its parent directory
|
|
20
|
+
# (i.e. page). For example, a page named 'foo' will have a directorynamed
|
|
21
|
+
# 'foo', with e.g. a 'foo.markdown' content file and a 'foo.yaml' meta file.
|
|
22
|
+
#
|
|
23
|
+
# Content file extensions are not used for determining the filter that
|
|
24
|
+
# should be run; the meta file defines the list of filters. The meta file
|
|
25
|
+
# extension must always be 'yaml', though.
|
|
26
|
+
#
|
|
27
|
+
# Content files can also have the 'index' basename. Similarly, meta files
|
|
28
|
+
# can have the 'meta' basename. For example, a parent directory named 'foo'
|
|
29
|
+
# can have an 'index.txt' content file and a 'meta.yaml' meta file. This is
|
|
30
|
+
# to preserve backward compatibility.
|
|
31
|
+
#
|
|
32
|
+
# = Page defaults
|
|
33
|
+
#
|
|
34
|
+
# The page defaults are loaded from a YAML-formatted file named
|
|
35
|
+
# 'page_defaults.yaml' at the top level of the nanoc site directory. For
|
|
36
|
+
# backward compatibility, the file can also be named 'meta.yaml'.
|
|
37
|
+
#
|
|
38
|
+
# = Assets
|
|
39
|
+
#
|
|
40
|
+
# Assets are stored in the 'assets' directory (surprise!). The structure is
|
|
41
|
+
# very similar to the structure of the 'content' directory, so see the Pages
|
|
42
|
+
# section for details on how this directory is structured.
|
|
43
|
+
#
|
|
44
|
+
# = Asset defaults
|
|
45
|
+
#
|
|
46
|
+
# The asset defaults are stored similar to the way page defaults are stored,
|
|
47
|
+
# except that the asset defaults file is named 'asset_defaults.yaml'
|
|
48
|
+
# instead.
|
|
49
|
+
#
|
|
50
|
+
# = Layouts
|
|
51
|
+
#
|
|
52
|
+
# Layouts are stored as directories in the 'layouts' directory. Each layout
|
|
53
|
+
# contains a content file and a meta file. The content file contain the
|
|
54
|
+
# actual layout, and the meta file describes how the page should be handled
|
|
55
|
+
# (contains the filter that should be used).
|
|
56
|
+
#
|
|
57
|
+
# For backward compatibility, a layout can also be a single file in the
|
|
58
|
+
# 'layouts' directory. Such a layout cannot have any metadata; the filter
|
|
59
|
+
# used for this layout is determined from the file extension.
|
|
60
|
+
#
|
|
61
|
+
# = Templates
|
|
62
|
+
#
|
|
63
|
+
# Templates are located in the 'templates' directroy. Every template is a
|
|
64
|
+
# directory consisting of a content file and a meta file, both named after
|
|
65
|
+
# the template. This is very similar to the way pages are stored, except
|
|
66
|
+
# that templates cannot be nested.
|
|
67
|
+
#
|
|
68
|
+
# = Code
|
|
69
|
+
#
|
|
70
|
+
# Code is stored in '.rb' files in the 'lib' directory. Code can reside in
|
|
71
|
+
# sub-directories.
|
|
72
|
+
class Filesystem < Nanoc::DataSource
|
|
73
|
+
|
|
74
|
+
PAGE_DEFAULTS_FILENAME = 'page_defaults.yaml'
|
|
75
|
+
PAGE_DEFAULTS_FILENAME_OLD = 'meta.yaml'
|
|
76
|
+
ASSET_DEFAULTS_FILENAME = 'asset_defaults.yaml'
|
|
4
77
|
|
|
5
78
|
########## Attributes ##########
|
|
6
79
|
|
|
7
80
|
identifier :filesystem
|
|
8
81
|
|
|
82
|
+
########## VCSes ##########
|
|
83
|
+
|
|
84
|
+
attr_accessor :vcs
|
|
85
|
+
|
|
86
|
+
def vcs
|
|
87
|
+
@vcs ||= Nanoc::Extra::VCSes::Dummy.new
|
|
88
|
+
end
|
|
89
|
+
|
|
9
90
|
########## Preparation ##########
|
|
10
91
|
|
|
11
|
-
def up
|
|
92
|
+
def up # :nodoc:
|
|
12
93
|
end
|
|
13
94
|
|
|
14
|
-
def down
|
|
95
|
+
def down # :nodoc:
|
|
15
96
|
end
|
|
16
97
|
|
|
17
|
-
def setup
|
|
18
|
-
# Create
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
FileManager.create_file 'content/content.yaml' do
|
|
23
|
-
"# Built-in\n" +
|
|
24
|
-
"\n" +
|
|
25
|
-
"# Custom\n" +
|
|
26
|
-
"title: \"A New Root Page\"\n"
|
|
98
|
+
def setup # :nodoc:
|
|
99
|
+
# Create directories
|
|
100
|
+
%w( assets content templates layouts lib ).each do |dir|
|
|
101
|
+
FileUtils.mkdir_p(dir)
|
|
102
|
+
vcs.add(dir)
|
|
27
103
|
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def destroy # :nodoc:
|
|
107
|
+
# Remove files
|
|
108
|
+
vcs.remove(ASSET_DEFAULTS_FILENAME) if File.file?(ASSET_DEFAULTS_FILENAME)
|
|
109
|
+
vcs.remove(PAGE_DEFAULTS_FILENAME) if File.file?(PAGE_DEFAULTS_FILENAME)
|
|
110
|
+
vcs.remove(PAGE_DEFAULTS_FILENAME_OLD) if File.file?(PAGE_DEFAULTS_FILENAME_OLD)
|
|
111
|
+
|
|
112
|
+
# Remove directories
|
|
113
|
+
vcs.remove('assets')
|
|
114
|
+
vcs.remove('content')
|
|
115
|
+
vcs.remove('templates')
|
|
116
|
+
vcs.remove('layouts')
|
|
117
|
+
vcs.remove('lib')
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def update # :nodoc:
|
|
121
|
+
update_page_defaults
|
|
122
|
+
update_pages
|
|
123
|
+
update_layouts
|
|
124
|
+
update_templates
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
########## Pages ##########
|
|
128
|
+
|
|
129
|
+
def pages # :nodoc:
|
|
130
|
+
meta_filenames('content').map do |meta_filename|
|
|
131
|
+
# Read metadata
|
|
132
|
+
meta = YAML.load_file(meta_filename) || {}
|
|
133
|
+
|
|
134
|
+
if meta['is_draft']
|
|
135
|
+
# Skip drafts
|
|
136
|
+
nil
|
|
137
|
+
else
|
|
138
|
+
# Get content
|
|
139
|
+
content_filename = content_filename_for_dir(File.dirname(meta_filename))
|
|
140
|
+
content = File.read(content_filename)
|
|
141
|
+
|
|
142
|
+
# Get attributes
|
|
143
|
+
attributes = meta.merge(:file => Nanoc::Extra::FileProxy.new(content_filename))
|
|
28
144
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
145
|
+
# Get path
|
|
146
|
+
path = meta_filename.sub(/^content/, '').sub(/[^\/]+\.yaml$/, '')
|
|
147
|
+
|
|
148
|
+
# Get modification times
|
|
149
|
+
meta_mtime = File.stat(meta_filename).mtime
|
|
150
|
+
content_mtime = File.stat(content_filename).mtime
|
|
151
|
+
mtime = meta_mtime > content_mtime ? meta_mtime : content_mtime
|
|
152
|
+
|
|
153
|
+
# Create page object
|
|
154
|
+
Nanoc::Page.new(content, attributes, path, mtime)
|
|
155
|
+
end
|
|
156
|
+
end.compact
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def save_page(page) # :nodoc:
|
|
160
|
+
# Determine possible meta file paths
|
|
161
|
+
last_component = page.path.split('/')[-1]
|
|
162
|
+
meta_filename_worst = 'content' + page.path + 'index.yaml'
|
|
163
|
+
meta_filename_best = 'content' + page.path + (last_component || 'content') + '.yaml'
|
|
164
|
+
|
|
165
|
+
# Get existing path
|
|
166
|
+
existing_path = nil
|
|
167
|
+
existing_path = meta_filename_best if File.file?(meta_filename_best)
|
|
168
|
+
existing_path = meta_filename_worst if File.file?(meta_filename_worst)
|
|
169
|
+
|
|
170
|
+
if existing_path.nil?
|
|
171
|
+
# Get filenames
|
|
172
|
+
dir_path = 'content' + page.path
|
|
173
|
+
meta_filename = meta_filename_best
|
|
174
|
+
content_filename = 'content' + page.path + (last_component || 'content') + '.html'
|
|
175
|
+
|
|
176
|
+
# Notify
|
|
177
|
+
Nanoc::NotificationCenter.post(:file_created, meta_filename)
|
|
178
|
+
Nanoc::NotificationCenter.post(:file_created, content_filename)
|
|
179
|
+
|
|
180
|
+
# Create directories if necessary
|
|
181
|
+
FileUtils.mkdir_p(dir_path)
|
|
182
|
+
else
|
|
183
|
+
# Get filenames
|
|
184
|
+
meta_filename = existing_path
|
|
185
|
+
content_filename = content_filename_for_dir(File.dirname(existing_path))
|
|
186
|
+
|
|
187
|
+
# Notify
|
|
188
|
+
Nanoc::NotificationCenter.post(:file_updated, meta_filename)
|
|
189
|
+
Nanoc::NotificationCenter.post(:file_updated, content_filename)
|
|
45
190
|
end
|
|
46
191
|
|
|
47
|
-
#
|
|
48
|
-
|
|
49
|
-
|
|
192
|
+
# Write files
|
|
193
|
+
File.open(meta_filename, 'w') { |io| io.write(page.attributes.to_split_yaml) }
|
|
194
|
+
File.open(content_filename, 'w') { |io| io.write(page.content) }
|
|
195
|
+
|
|
196
|
+
# Add to working copy if possible
|
|
197
|
+
if existing_path.nil?
|
|
198
|
+
vcs.add(meta_filename)
|
|
199
|
+
vcs.add(content_filename)
|
|
50
200
|
end
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def move_page(page, new_path) # :nodoc:
|
|
204
|
+
# TODO implement
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def delete_page(page) # :nodoc:
|
|
208
|
+
# TODO implement
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
########## Assets ##########
|
|
212
|
+
|
|
213
|
+
def assets # :nodoc:
|
|
214
|
+
meta_filenames('assets').map do |meta_filename|
|
|
215
|
+
# Read metadata
|
|
216
|
+
meta = YAML.load_file(meta_filename) || {}
|
|
217
|
+
|
|
218
|
+
# Get content file
|
|
219
|
+
content_filename = content_filename_for_dir(File.dirname(meta_filename))
|
|
220
|
+
content_file = File.new(content_filename)
|
|
221
|
+
|
|
222
|
+
# Get attributes
|
|
223
|
+
attributes = meta.merge(:extension => File.extname(content_filename)[1..-1])
|
|
224
|
+
|
|
225
|
+
# Get path
|
|
226
|
+
path = meta_filename.sub(/^assets/, '').sub(/[^\/]+\.yaml$/, '')
|
|
227
|
+
|
|
228
|
+
# Get modification times
|
|
229
|
+
meta_mtime = File.stat(meta_filename).mtime
|
|
230
|
+
content_mtime = File.stat(content_filename).mtime
|
|
231
|
+
mtime = meta_mtime > content_mtime ? meta_mtime : content_mtime
|
|
232
|
+
|
|
233
|
+
# Create asset object
|
|
234
|
+
Nanoc::Asset.new(content_file, attributes, path, mtime)
|
|
56
235
|
end
|
|
236
|
+
end
|
|
57
237
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
238
|
+
def save_asset(asset) # :nodoc:
|
|
239
|
+
# Determine meta file path
|
|
240
|
+
last_component = asset.path.split('/')[-1]
|
|
241
|
+
meta_filename = 'assets' + asset.path + last_component + '.yaml'
|
|
242
|
+
|
|
243
|
+
# Get existing path
|
|
244
|
+
existing_path = nil
|
|
245
|
+
existing_path = meta_filename_best if File.file?(meta_filename_best)
|
|
246
|
+
existing_path = meta_filename_worst if File.file?(meta_filename_worst)
|
|
247
|
+
|
|
248
|
+
if meta_filename.nil?
|
|
249
|
+
# Get filenames
|
|
250
|
+
dir_path = 'assets' + asset.path
|
|
251
|
+
content_filename = 'assets' + asset.path + last_component + '.dat'
|
|
252
|
+
|
|
253
|
+
# Notify
|
|
254
|
+
Nanoc::NotificationCenter.post(:file_created, meta_filename)
|
|
255
|
+
Nanoc::NotificationCenter.post(:file_created, content_filename)
|
|
256
|
+
|
|
257
|
+
# Create directories if necessary
|
|
258
|
+
FileUtils.mkdir_p(dir_path)
|
|
259
|
+
else
|
|
260
|
+
# Get filenames
|
|
261
|
+
content_filename = content_filename_for_dir(File.dirname(meta_filename))
|
|
262
|
+
|
|
263
|
+
# Notify
|
|
264
|
+
Nanoc::NotificationCenter.post(:file_updated, meta_filename)
|
|
265
|
+
Nanoc::NotificationCenter.post(:file_updated, content_filename)
|
|
68
266
|
end
|
|
69
267
|
|
|
70
|
-
#
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
"alias h html_escape\n"
|
|
268
|
+
# Write files
|
|
269
|
+
File.open(meta_filename, 'w') { |io| io.write(asset.attributes.to_split_yaml) }
|
|
270
|
+
File.open(content_filename, 'w') { }
|
|
271
|
+
|
|
272
|
+
# Add to working copy if possible
|
|
273
|
+
if meta_filename.nil?
|
|
274
|
+
vcs.add(meta_filename)
|
|
275
|
+
vcs.add(content_filename)
|
|
79
276
|
end
|
|
277
|
+
end
|
|
80
278
|
|
|
279
|
+
def move_asset(asset, new_path) # :nodoc:
|
|
280
|
+
# TODO implement
|
|
81
281
|
end
|
|
82
282
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
# directory represents a single page. The root directory is the 'content'
|
|
87
|
-
# directory.
|
|
88
|
-
#
|
|
89
|
-
# Every directory has a content file and a meta file. The content file
|
|
90
|
-
# contains the actual page content, while the meta file contains the
|
|
91
|
-
# page's metadata.
|
|
92
|
-
#
|
|
93
|
-
# Both content files and meta files are named after its parent directory
|
|
94
|
-
# (i.e. page). For example, a page named 'foo' will have a directory named
|
|
95
|
-
# 'foo', with e.g. a 'foo.markdown' content file and a 'foo.yaml' meta
|
|
96
|
-
# file.
|
|
97
|
-
#
|
|
98
|
-
# Content file extensions are ignored by nanoc. The content file extension
|
|
99
|
-
# does not determine the filters to run on it; the meta file defines the
|
|
100
|
-
# list of filters. The meta file extension must always be 'yaml', though.
|
|
101
|
-
#
|
|
102
|
-
# Content files can also have the 'index' basename. Similarly, meta files
|
|
103
|
-
# can have the 'meta' basename. For example, a parent directory named
|
|
104
|
-
# 'foo' can have an 'index.txt' content file and a 'meta.yaml' meta file.
|
|
105
|
-
# This is to preserve backward compatibility.
|
|
106
|
-
def pages
|
|
107
|
-
meta_filenames.inject([]) do |pages, filename|
|
|
108
|
-
# Read metadata
|
|
109
|
-
meta = (YAML.load_file(filename) || {}).clean
|
|
283
|
+
def delete_asset(asset) # :nodoc:
|
|
284
|
+
# TODO implement
|
|
285
|
+
end
|
|
110
286
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
287
|
+
########## Page Defaults ##########
|
|
288
|
+
|
|
289
|
+
def page_defaults # :nodoc:
|
|
290
|
+
# Get attributes
|
|
291
|
+
filename = File.file?(PAGE_DEFAULTS_FILENAME) ? PAGE_DEFAULTS_FILENAME : PAGE_DEFAULTS_FILENAME_OLD
|
|
292
|
+
attributes = YAML.load_file(filename) || {}
|
|
293
|
+
|
|
294
|
+
# Get mtime
|
|
295
|
+
mtime = File.stat(filename).mtime
|
|
296
|
+
|
|
297
|
+
# Build page defaults
|
|
298
|
+
Nanoc::PageDefaults.new(attributes, mtime)
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
def save_page_defaults(page_defaults) # :nodoc:
|
|
302
|
+
# Notify
|
|
303
|
+
if File.file?(PAGE_DEFAULTS_FILENAME)
|
|
304
|
+
filename = PAGE_DEFAULTS_FILENAME
|
|
305
|
+
created = false
|
|
306
|
+
Nanoc::NotificationCenter.post(:file_updated, filename)
|
|
307
|
+
elsif File.file?(PAGE_DEFAULTS_FILENAME_OLD)
|
|
308
|
+
filename = PAGE_DEFAULTS_FILENAME_OLD
|
|
309
|
+
created = false
|
|
310
|
+
Nanoc::NotificationCenter.post(:file_updated, filename)
|
|
311
|
+
else
|
|
312
|
+
filename = PAGE_DEFAULTS_FILENAME
|
|
313
|
+
created = true
|
|
314
|
+
Nanoc::NotificationCenter.post(:file_created, filename)
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
# Write
|
|
318
|
+
File.open(filename, 'w') do |io|
|
|
319
|
+
io.write(page_defaults.attributes.to_split_yaml)
|
|
127
320
|
end
|
|
321
|
+
|
|
322
|
+
# Add to working copy if possible
|
|
323
|
+
vcs.add(filename) if created
|
|
128
324
|
end
|
|
129
325
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
326
|
+
########## Asset Defaults ##########
|
|
327
|
+
|
|
328
|
+
def asset_defaults # :nodoc:
|
|
329
|
+
if File.file?(ASSET_DEFAULTS_FILENAME)
|
|
330
|
+
# Get attributes
|
|
331
|
+
attributes = YAML.load_file(ASSET_DEFAULTS_FILENAME) || {}
|
|
332
|
+
|
|
333
|
+
# Get mtime
|
|
334
|
+
mtime = File.stat(ASSET_DEFAULTS_FILENAME).mtime
|
|
335
|
+
|
|
336
|
+
# Build asset defaults
|
|
337
|
+
Nanoc::AssetDefaults.new(attributes, mtime)
|
|
338
|
+
else
|
|
339
|
+
Nanoc::AssetDefaults.new({})
|
|
340
|
+
end
|
|
133
341
|
end
|
|
134
342
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
name = File.basename(filename, extension)
|
|
145
|
-
content = File.read(filename)
|
|
343
|
+
def save_asset_defaults(asset_defaults) # :nodoc:
|
|
344
|
+
# Notify
|
|
345
|
+
if File.file?(ASSET_DEFAULTS_FILENAME)
|
|
346
|
+
Nanoc::NotificationCenter.post(:file_updated, ASSET_DEFAULTS_FILENAME)
|
|
347
|
+
created = false
|
|
348
|
+
else
|
|
349
|
+
Nanoc::NotificationCenter.post(:file_created, ASSET_DEFAULTS_FILENAME)
|
|
350
|
+
created = true
|
|
351
|
+
end
|
|
146
352
|
|
|
147
|
-
|
|
148
|
-
|
|
353
|
+
# Write
|
|
354
|
+
File.open(ASSET_DEFAULTS_FILENAME, 'w') do |io|
|
|
355
|
+
io.write(asset_defaults.attributes.to_split_yaml)
|
|
149
356
|
end
|
|
357
|
+
|
|
358
|
+
# Add to working copy if possible
|
|
359
|
+
vcs.add(ASSET_DEFAULTS_FILENAME) if created
|
|
150
360
|
end
|
|
151
361
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
362
|
+
########## Layouts ##########
|
|
363
|
+
|
|
364
|
+
def layouts # :nodoc:
|
|
365
|
+
# Determine what layout directory structure is being used
|
|
366
|
+
dir_count = Dir[File.join('layouts', '*')].select { |f| File.directory?(f) }.size
|
|
367
|
+
is_old_school = (dir_count == 0)
|
|
368
|
+
|
|
369
|
+
if is_old_school
|
|
370
|
+
# Warn about deprecation
|
|
371
|
+
warn(
|
|
372
|
+
'nanoc 2.1 changes the way layouts are stored. Future versions will not support these outdated sites. To update your site, issue \'nanoc update\'.',
|
|
373
|
+
'DEPRECATION WARNING'
|
|
374
|
+
)
|
|
375
|
+
|
|
376
|
+
Dir[File.join('layouts', '*')].reject { |f| f =~ /~$/ }.map do |filename|
|
|
377
|
+
# Get content
|
|
378
|
+
content = File.read(filename)
|
|
379
|
+
|
|
380
|
+
# Get attributes
|
|
381
|
+
attributes = { :extension => File.extname(filename)}
|
|
382
|
+
|
|
383
|
+
# Get path
|
|
384
|
+
path = File.basename(filename, attributes[:extension])
|
|
385
|
+
|
|
386
|
+
# Get modification time
|
|
387
|
+
mtime = File.stat(filename).mtime
|
|
388
|
+
|
|
389
|
+
# Create layout object
|
|
390
|
+
Nanoc::Layout.new(content, attributes, path, mtime)
|
|
391
|
+
end
|
|
392
|
+
else
|
|
393
|
+
meta_filenames('layouts').map do |meta_filename|
|
|
394
|
+
# Get content
|
|
395
|
+
content_filename = content_filename_for_dir(File.dirname(meta_filename))
|
|
396
|
+
content = File.read(content_filename)
|
|
397
|
+
|
|
398
|
+
# Get attributes
|
|
399
|
+
attributes = YAML.load_file(meta_filename) || {}
|
|
400
|
+
|
|
401
|
+
# Get path
|
|
402
|
+
path = meta_filename.sub(/^layouts\//, '').sub(/\/[^\/]+\.yaml$/, '')
|
|
403
|
+
|
|
404
|
+
# Get modification times
|
|
405
|
+
meta_mtime = File.stat(meta_filename).mtime
|
|
406
|
+
content_mtime = File.stat(content_filename).mtime
|
|
407
|
+
mtime = meta_mtime > content_mtime ? meta_mtime : content_mtime
|
|
408
|
+
|
|
409
|
+
# Create layout object
|
|
410
|
+
Nanoc::Layout.new(content, attributes, path, mtime)
|
|
173
411
|
end
|
|
174
|
-
meta = File.read(meta_filename)
|
|
175
|
-
|
|
176
|
-
# Add it to the list of templates
|
|
177
|
-
templates + [{
|
|
178
|
-
:name => name,
|
|
179
|
-
:extension => extension,
|
|
180
|
-
:content => content,
|
|
181
|
-
:meta => meta
|
|
182
|
-
}]
|
|
183
412
|
end
|
|
184
413
|
end
|
|
185
414
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
415
|
+
def save_layout(layout) # :nodoc:
|
|
416
|
+
# Determine what layout directory structure is being used
|
|
417
|
+
layout_file_count = Dir[File.join('layouts', '*')].select { |f| File.file?(f) }.size
|
|
418
|
+
error_outdated if layout_file_count > 0
|
|
419
|
+
|
|
420
|
+
# Get paths
|
|
421
|
+
last_component = layout.path.split('/')[-1]
|
|
422
|
+
dir_path = 'layouts' + layout.path
|
|
423
|
+
meta_filename = dir_path + last_component + '.yaml'
|
|
424
|
+
content_filename = Dir[dir_path + last_component + '.*'][0]
|
|
425
|
+
|
|
426
|
+
if File.file?(meta_filename)
|
|
427
|
+
created = false
|
|
428
|
+
|
|
429
|
+
# Notify
|
|
430
|
+
Nanoc::NotificationCenter.post(:file_updated, meta_filename)
|
|
431
|
+
Nanoc::NotificationCenter.post(:file_updated, content_filename)
|
|
432
|
+
else
|
|
433
|
+
created = true
|
|
434
|
+
|
|
435
|
+
# Create dir
|
|
436
|
+
FileUtils.mkdir_p(dir_path)
|
|
437
|
+
|
|
438
|
+
# Get content filename
|
|
439
|
+
content_filename = dir_path + last_component + '.html'
|
|
440
|
+
|
|
441
|
+
# Notify
|
|
442
|
+
Nanoc::NotificationCenter.post(:file_created, meta_filename)
|
|
443
|
+
Nanoc::NotificationCenter.post(:file_created, content_filename)
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
# Write files
|
|
447
|
+
File.open(meta_filename, 'w') { |io| io.write(layout.attributes.to_split_yaml) }
|
|
448
|
+
File.open(content_filename, 'w') { |io| io.write(layout.content) }
|
|
449
|
+
|
|
450
|
+
# Add to working copy if possible
|
|
451
|
+
if created
|
|
452
|
+
vcs.add(meta_filename)
|
|
453
|
+
vcs.add(content_filename)
|
|
454
|
+
end
|
|
190
455
|
end
|
|
191
456
|
|
|
192
|
-
|
|
457
|
+
def move_layout(layout, new_path) # :nodoc:
|
|
458
|
+
# TODO implement
|
|
459
|
+
end
|
|
460
|
+
|
|
461
|
+
def delete_layout(layout) # :nodoc:
|
|
462
|
+
# TODO implement
|
|
463
|
+
end
|
|
193
464
|
|
|
194
|
-
|
|
195
|
-
# the 'content' directory, as well as a content file named xxx.txt and a
|
|
196
|
-
# meta file named xxx.yaml (with xxx being the name of the page).
|
|
197
|
-
def create_page(path, template)
|
|
198
|
-
# Make sure path does not start or end with a slash
|
|
199
|
-
sanitized_path = path.gsub(/^\/+|\/+$/, '')
|
|
465
|
+
########## Templates ##########
|
|
200
466
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
# Creating a layout creates a single file in the 'layouts' directory,
|
|
216
|
-
# named xxx.erb (with xxx being the name of the layout).
|
|
217
|
-
def create_layout(name)
|
|
218
|
-
# Get details
|
|
219
|
-
path = 'layouts/' + name + '.erb'
|
|
220
|
-
|
|
221
|
-
# Make sure the layout doesn't exist yet
|
|
222
|
-
error "A layout named '#{name}' already exists." if File.exist?(path)
|
|
223
|
-
|
|
224
|
-
# Create layout file
|
|
225
|
-
FileManager.create_file(path) do
|
|
226
|
-
"<html>\n" +
|
|
227
|
-
" <head>\n" +
|
|
228
|
-
" <title><%= @page.title %></title>\n" +
|
|
229
|
-
" </head>\n" +
|
|
230
|
-
" <body>\n" +
|
|
231
|
-
"<%= @page.content %>\n" +
|
|
232
|
-
" </body>\n" +
|
|
233
|
-
"</html>\n"
|
|
467
|
+
def templates # :nodoc:
|
|
468
|
+
meta_filenames('templates').map do |meta_filename|
|
|
469
|
+
# Get name
|
|
470
|
+
name = meta_filename.sub(/^templates\/(.*)\/[^\/]+\.yaml$/, '\1')
|
|
471
|
+
|
|
472
|
+
# Get content
|
|
473
|
+
content_filename = content_filename_for_dir(File.dirname(meta_filename))
|
|
474
|
+
content = File.read(content_filename)
|
|
475
|
+
|
|
476
|
+
# Get attributes
|
|
477
|
+
attributes = YAML.load_file(meta_filename) || {}
|
|
478
|
+
|
|
479
|
+
# Build template
|
|
480
|
+
Nanoc::Template.new(content, attributes, name)
|
|
234
481
|
end
|
|
235
482
|
end
|
|
236
483
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
# Get
|
|
243
|
-
|
|
244
|
-
|
|
484
|
+
def save_template(template) # :nodoc:
|
|
485
|
+
# Determine possible meta file paths
|
|
486
|
+
meta_filename_worst = 'templates/' + template.name + '/index.yaml'
|
|
487
|
+
meta_filename_best = 'templates/' + template.name + '/' + template.name + '.yaml'
|
|
488
|
+
|
|
489
|
+
# Get existing path
|
|
490
|
+
existing_path = nil
|
|
491
|
+
existing_path = meta_filename_best if File.file?(meta_filename_best)
|
|
492
|
+
existing_path = meta_filename_worst if File.file?(meta_filename_worst)
|
|
493
|
+
|
|
494
|
+
if existing_path.nil?
|
|
495
|
+
# Get filenames
|
|
496
|
+
dir_path = 'templates/' + template.name
|
|
497
|
+
meta_filename = meta_filename_best
|
|
498
|
+
content_filename = 'templates/' + template.name + '/' + template.name + '.html'
|
|
499
|
+
|
|
500
|
+
# Notify
|
|
501
|
+
Nanoc::NotificationCenter.post(:file_created, meta_filename)
|
|
502
|
+
Nanoc::NotificationCenter.post(:file_created, content_filename)
|
|
503
|
+
|
|
504
|
+
# Create directories if necessary
|
|
505
|
+
FileUtils.mkdir_p(dir_path)
|
|
506
|
+
else
|
|
507
|
+
# Get filenames
|
|
508
|
+
meta_filename = existing_path
|
|
509
|
+
content_filename = content_filename_for_dir(File.dirname(existing_path))
|
|
510
|
+
|
|
511
|
+
# Notify
|
|
512
|
+
Nanoc::NotificationCenter.post(:file_updated, meta_filename)
|
|
513
|
+
Nanoc::NotificationCenter.post(:file_updated, content_filename)
|
|
514
|
+
end
|
|
515
|
+
|
|
516
|
+
# Write files
|
|
517
|
+
File.open(meta_filename, 'w') { |io| io.write(template.page_attributes.to_split_yaml) }
|
|
518
|
+
File.open(content_filename, 'w') { |io| io.write(template.page_content) }
|
|
519
|
+
|
|
520
|
+
# Add to working copy if possible
|
|
521
|
+
if existing_path.nil?
|
|
522
|
+
vcs.add(meta_filename)
|
|
523
|
+
vcs.add(content_filename)
|
|
524
|
+
end
|
|
525
|
+
end
|
|
526
|
+
|
|
527
|
+
def move_template(template, new_name) # :nodoc:
|
|
528
|
+
# TODO implement
|
|
529
|
+
end
|
|
530
|
+
|
|
531
|
+
def delete_template(template) # :nodoc:
|
|
532
|
+
# TODO implement
|
|
533
|
+
end
|
|
534
|
+
|
|
535
|
+
########## Code ##########
|
|
536
|
+
|
|
537
|
+
def code # :nodoc:
|
|
538
|
+
# Get files
|
|
539
|
+
filenames = Dir['lib/**/*.rb'].sort
|
|
540
|
+
|
|
541
|
+
# Get data
|
|
542
|
+
data = filenames.map { |filename| File.read(filename) + "\n" }.join('')
|
|
543
|
+
|
|
544
|
+
# Get modification time
|
|
545
|
+
mtimes = filenames.map { |filename| File.stat(filename).mtime }
|
|
546
|
+
mtime = mtimes.inject { |memo, mtime| memo > mtime ? mtime : memo }
|
|
245
547
|
|
|
246
|
-
#
|
|
247
|
-
|
|
548
|
+
# Build code
|
|
549
|
+
Nanoc::Code.new(data, mtime)
|
|
550
|
+
end
|
|
551
|
+
|
|
552
|
+
def save_code(code) # :nodoc:
|
|
553
|
+
# Check whether code existed
|
|
554
|
+
existed = File.file?('lib/default.rb')
|
|
248
555
|
|
|
249
|
-
#
|
|
250
|
-
|
|
251
|
-
|
|
556
|
+
# Remove all existing code files
|
|
557
|
+
Dir['lib/**/*.rb'].each do |file|
|
|
558
|
+
vcs.remove(file) unless file == 'lib/default.rb'
|
|
559
|
+
end
|
|
560
|
+
|
|
561
|
+
# Notify
|
|
562
|
+
if existed
|
|
563
|
+
Nanoc::NotificationCenter.post(:file_updated, 'lib/default.rb')
|
|
564
|
+
else
|
|
565
|
+
Nanoc::NotificationCenter.post(:file_created, 'lib/default.rb')
|
|
566
|
+
end
|
|
567
|
+
|
|
568
|
+
# Write new code
|
|
569
|
+
File.open('lib/default.rb', 'w') do |io|
|
|
570
|
+
io.write(code.data)
|
|
571
|
+
end
|
|
572
|
+
|
|
573
|
+
# Add to working copy if possible
|
|
574
|
+
vcs.add('lib/default.rb') unless existed
|
|
252
575
|
end
|
|
253
576
|
|
|
254
577
|
private
|
|
255
578
|
|
|
256
579
|
########## Custom functions ##########
|
|
257
580
|
|
|
258
|
-
# Returns the list of meta files in the given
|
|
259
|
-
|
|
581
|
+
# Returns the list of all meta files in the given base directory as well
|
|
582
|
+
# as its subdirectories.
|
|
583
|
+
def meta_filenames(base)
|
|
260
584
|
# Find all possible meta file names
|
|
261
585
|
filenames = Dir[base + '/**/*.yaml']
|
|
262
586
|
|
|
@@ -273,16 +597,20 @@ module Nanoc::DataSource::Filesystem
|
|
|
273
597
|
|
|
274
598
|
# Warn about bad filenames
|
|
275
599
|
unless bad_filenames.empty?
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
600
|
+
raise RuntimeError.new(
|
|
601
|
+
"The following files appear to be meta files, " +
|
|
602
|
+
"but have an invalid name:\n - " +
|
|
603
|
+
bad_filenames.join("\n - ")
|
|
604
|
+
)
|
|
279
605
|
end
|
|
280
606
|
|
|
281
607
|
good_filenames
|
|
282
608
|
end
|
|
283
609
|
|
|
284
|
-
# Returns
|
|
285
|
-
|
|
610
|
+
# Returns the filename of the content file in the given directory,
|
|
611
|
+
# ignoring any unwanted files (files that end with '~', '.orig', '.rej' or
|
|
612
|
+
# '.bak')
|
|
613
|
+
def content_filename_for_dir(dir)
|
|
286
614
|
# Find all files
|
|
287
615
|
filename_glob_1 = dir.sub(/([^\/]+)$/, '\1/\1.*')
|
|
288
616
|
filename_glob_2 = dir.sub(/([^\/]+)$/, '\1/index.*')
|
|
@@ -292,15 +620,122 @@ module Nanoc::DataSource::Filesystem
|
|
|
292
620
|
filenames.reject! { |f| f =~ /\.yaml$/ }
|
|
293
621
|
|
|
294
622
|
# Reject backups
|
|
295
|
-
filenames.reject! { |f| f =~
|
|
623
|
+
filenames.reject! { |f| f =~ /(~|\.orig|\.rej|\.bak)$/ }
|
|
296
624
|
|
|
297
625
|
# Make sure there is only one content file
|
|
298
626
|
if filenames.size != 1
|
|
299
|
-
|
|
627
|
+
raise RuntimeError.new(
|
|
628
|
+
"Expected 1 content file in #{dir} but found #{filenames.size}"
|
|
629
|
+
)
|
|
630
|
+
end
|
|
631
|
+
|
|
632
|
+
# Return content filename
|
|
633
|
+
filenames.first
|
|
634
|
+
end
|
|
635
|
+
|
|
636
|
+
# Raises an "outdated data format" error.
|
|
637
|
+
def error_outdated
|
|
638
|
+
raise RuntimeError.new(
|
|
639
|
+
'This site\'s data is stored in an old format and must be updated. ' +
|
|
640
|
+
'To do so, issue the \'nanoc update\' command. For help on ' +
|
|
641
|
+
'updating a site\'s data, issue \'nanoc help update\'.'
|
|
642
|
+
)
|
|
643
|
+
end
|
|
644
|
+
|
|
645
|
+
# Updated outdated page defaults (renames page defaults file)
|
|
646
|
+
def update_page_defaults
|
|
647
|
+
return unless File.file?(PAGE_DEFAULTS_FILENAME_OLD)
|
|
648
|
+
|
|
649
|
+
vcs.move(PAGE_DEFAULTS_FILENAME_OLD, PAGE_DEFAULTS_FILENAME)
|
|
650
|
+
end
|
|
651
|
+
|
|
652
|
+
# Updates outdated pages (both content and meta file names).
|
|
653
|
+
def update_pages
|
|
654
|
+
# Update content files
|
|
655
|
+
# content/foo/bar/baz/index.ext -> content/foo/bar/baz/baz.ext
|
|
656
|
+
Dir['content/**/index.*'].select { |f| File.file?(f) }.each do |old_filename|
|
|
657
|
+
# Determine new name
|
|
658
|
+
if old_filename =~ /^content\/index\./
|
|
659
|
+
new_filename = old_filename.sub(/^content\/index\./, 'content/content.')
|
|
660
|
+
else
|
|
661
|
+
new_filename = old_filename.sub(/([^\/]+)\/index\.([^\/]+)$/, '\1/\1.\2')
|
|
662
|
+
end
|
|
663
|
+
|
|
664
|
+
# Move
|
|
665
|
+
vcs.move(old_filename, new_filename)
|
|
300
666
|
end
|
|
301
667
|
|
|
302
|
-
#
|
|
303
|
-
|
|
668
|
+
# Update meta files
|
|
669
|
+
# content/foo/bar/baz/meta.yaml -> content/foo/bar/baz/baz.yaml
|
|
670
|
+
Dir['content/**/meta.yaml'].select { |f| File.file?(f) }.each do |old_filename|
|
|
671
|
+
# Determine new name
|
|
672
|
+
if old_filename == 'content/meta.yaml'
|
|
673
|
+
new_filename = 'content/content.yaml'
|
|
674
|
+
else
|
|
675
|
+
new_filename = old_filename.sub(/([^\/]+)\/meta.yaml$/, '\1/\1.yaml')
|
|
676
|
+
end
|
|
677
|
+
|
|
678
|
+
# Move
|
|
679
|
+
vcs.move(old_filename, new_filename)
|
|
680
|
+
end
|
|
681
|
+
end
|
|
682
|
+
|
|
683
|
+
# Updates outdated layouts.
|
|
684
|
+
def update_layouts
|
|
685
|
+
# layouts/abc.ext -> layouts/abc/abc.{html,yaml}
|
|
686
|
+
Dir[File.join('layouts', '*')].select { |f| File.file?(f) }.each do |filename|
|
|
687
|
+
# Get filter class
|
|
688
|
+
filter_class = Nanoc::Filter.with_extension(File.extname(filename))
|
|
689
|
+
|
|
690
|
+
# Get data
|
|
691
|
+
content = File.read(filename)
|
|
692
|
+
attributes = { :filter => filter_class.identifier.to_s }
|
|
693
|
+
path = File.basename(filename, File.extname(filename))
|
|
694
|
+
|
|
695
|
+
# Get layout
|
|
696
|
+
tmp_layout = Nanoc::Layout.new(content, attributes, path)
|
|
697
|
+
|
|
698
|
+
# Get filenames
|
|
699
|
+
last_component = tmp_layout.path.split('/')[-1]
|
|
700
|
+
dir_path = 'layouts' + tmp_layout.path
|
|
701
|
+
meta_filename = dir_path + last_component + '.yaml'
|
|
702
|
+
content_filename = dir_path + last_component + File.extname(filename)
|
|
703
|
+
|
|
704
|
+
# Create new files
|
|
705
|
+
FileUtils.mkdir_p(dir_path)
|
|
706
|
+
File.open(meta_filename, 'w') { |io| io.write(tmp_layout.attributes.to_split_yaml) }
|
|
707
|
+
File.open(content_filename, 'w') { |io| io.write(tmp_layout.content) }
|
|
708
|
+
|
|
709
|
+
# Add
|
|
710
|
+
vcs.add(meta_filename)
|
|
711
|
+
vcs.add(content_filename)
|
|
712
|
+
|
|
713
|
+
# Delete old files
|
|
714
|
+
vcs.remove(filename)
|
|
715
|
+
end
|
|
716
|
+
end
|
|
717
|
+
|
|
718
|
+
# Updates outdated templates (both content and meta file names).
|
|
719
|
+
def update_templates
|
|
720
|
+
# Update content files
|
|
721
|
+
# templates/foo/index.ext -> templates/foo/foo.ext
|
|
722
|
+
Dir['templates/**/index.*'].select { |f| File.file?(f) }.each do |old_filename|
|
|
723
|
+
# Determine new name
|
|
724
|
+
new_filename = old_filename.sub(/([^\/]+)\/index\.([^\/]+)$/, '\1/\1.\2')
|
|
725
|
+
|
|
726
|
+
# Move
|
|
727
|
+
vcs.move(old_filename, new_filename)
|
|
728
|
+
end
|
|
729
|
+
|
|
730
|
+
# Update meta files
|
|
731
|
+
# templates/foo/meta.yaml -> templates/foo/foo.yaml
|
|
732
|
+
Dir['templates/**/meta.yaml'].select { |f| File.file?(f) }.each do |old_filename|
|
|
733
|
+
# Determine new name
|
|
734
|
+
new_filename = old_filename.sub(/([^\/]+)\/meta.yaml$/, '\1/\1.yaml')
|
|
735
|
+
|
|
736
|
+
# Move
|
|
737
|
+
vcs.move(old_filename, new_filename)
|
|
738
|
+
end
|
|
304
739
|
end
|
|
305
740
|
|
|
306
741
|
end
|