nanoc 2.2.2 → 3.0.0a1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. data/bin/nanoc +29 -11
  2. data/bin/nanoc-select +85 -0
  3. metadata +27 -161
  4. data/ChangeLog +0 -3
  5. data/LICENSE +0 -19
  6. data/README +0 -75
  7. data/Rakefile +0 -76
  8. data/lib/nanoc.rb +0 -73
  9. data/lib/nanoc/base.rb +0 -26
  10. data/lib/nanoc/base/asset.rb +0 -117
  11. data/lib/nanoc/base/asset_defaults.rb +0 -21
  12. data/lib/nanoc/base/asset_rep.rb +0 -282
  13. data/lib/nanoc/base/binary_filter.rb +0 -44
  14. data/lib/nanoc/base/code.rb +0 -41
  15. data/lib/nanoc/base/compiler.rb +0 -67
  16. data/lib/nanoc/base/core_ext.rb +0 -2
  17. data/lib/nanoc/base/core_ext/hash.rb +0 -78
  18. data/lib/nanoc/base/core_ext/string.rb +0 -8
  19. data/lib/nanoc/base/data_source.rb +0 -286
  20. data/lib/nanoc/base/defaults.rb +0 -30
  21. data/lib/nanoc/base/filter.rb +0 -93
  22. data/lib/nanoc/base/layout.rb +0 -91
  23. data/lib/nanoc/base/notification_center.rb +0 -66
  24. data/lib/nanoc/base/page.rb +0 -132
  25. data/lib/nanoc/base/page_defaults.rb +0 -20
  26. data/lib/nanoc/base/page_rep.rb +0 -324
  27. data/lib/nanoc/base/plugin.rb +0 -71
  28. data/lib/nanoc/base/proxies.rb +0 -5
  29. data/lib/nanoc/base/proxies/asset_proxy.rb +0 -29
  30. data/lib/nanoc/base/proxies/asset_rep_proxy.rb +0 -26
  31. data/lib/nanoc/base/proxies/layout_proxy.rb +0 -25
  32. data/lib/nanoc/base/proxies/page_proxy.rb +0 -35
  33. data/lib/nanoc/base/proxies/page_rep_proxy.rb +0 -28
  34. data/lib/nanoc/base/proxy.rb +0 -37
  35. data/lib/nanoc/base/router.rb +0 -72
  36. data/lib/nanoc/base/site.rb +0 -274
  37. data/lib/nanoc/base/template.rb +0 -64
  38. data/lib/nanoc/binary_filters.rb +0 -1
  39. data/lib/nanoc/binary_filters/image_science_thumbnail.rb +0 -28
  40. data/lib/nanoc/cli.rb +0 -9
  41. data/lib/nanoc/cli/base.rb +0 -132
  42. data/lib/nanoc/cli/commands.rb +0 -10
  43. data/lib/nanoc/cli/commands/autocompile.rb +0 -80
  44. data/lib/nanoc/cli/commands/compile.rb +0 -311
  45. data/lib/nanoc/cli/commands/create_layout.rb +0 -85
  46. data/lib/nanoc/cli/commands/create_page.rb +0 -85
  47. data/lib/nanoc/cli/commands/create_site.rb +0 -323
  48. data/lib/nanoc/cli/commands/create_template.rb +0 -76
  49. data/lib/nanoc/cli/commands/help.rb +0 -69
  50. data/lib/nanoc/cli/commands/info.rb +0 -125
  51. data/lib/nanoc/cli/commands/switch.rb +0 -141
  52. data/lib/nanoc/cli/commands/update.rb +0 -91
  53. data/lib/nanoc/cli/logger.rb +0 -72
  54. data/lib/nanoc/data_sources.rb +0 -2
  55. data/lib/nanoc/data_sources/filesystem.rb +0 -707
  56. data/lib/nanoc/data_sources/filesystem_combined.rb +0 -495
  57. data/lib/nanoc/extra.rb +0 -6
  58. data/lib/nanoc/extra/auto_compiler.rb +0 -285
  59. data/lib/nanoc/extra/context.rb +0 -22
  60. data/lib/nanoc/extra/core_ext.rb +0 -2
  61. data/lib/nanoc/extra/core_ext/hash.rb +0 -54
  62. data/lib/nanoc/extra/core_ext/time.rb +0 -13
  63. data/lib/nanoc/extra/file_proxy.rb +0 -29
  64. data/lib/nanoc/extra/vcs.rb +0 -48
  65. data/lib/nanoc/extra/vcses.rb +0 -5
  66. data/lib/nanoc/extra/vcses/bazaar.rb +0 -21
  67. data/lib/nanoc/extra/vcses/dummy.rb +0 -20
  68. data/lib/nanoc/extra/vcses/git.rb +0 -21
  69. data/lib/nanoc/extra/vcses/mercurial.rb +0 -21
  70. data/lib/nanoc/extra/vcses/subversion.rb +0 -21
  71. data/lib/nanoc/filters.rb +0 -16
  72. data/lib/nanoc/filters/bluecloth.rb +0 -13
  73. data/lib/nanoc/filters/erb.rb +0 -19
  74. data/lib/nanoc/filters/erubis.rb +0 -14
  75. data/lib/nanoc/filters/haml.rb +0 -21
  76. data/lib/nanoc/filters/markaby.rb +0 -14
  77. data/lib/nanoc/filters/maruku.rb +0 -14
  78. data/lib/nanoc/filters/old.rb +0 -19
  79. data/lib/nanoc/filters/rainpress.rb +0 -13
  80. data/lib/nanoc/filters/rdiscount.rb +0 -13
  81. data/lib/nanoc/filters/rdoc.rb +0 -23
  82. data/lib/nanoc/filters/redcloth.rb +0 -14
  83. data/lib/nanoc/filters/relativize_paths.rb +0 -16
  84. data/lib/nanoc/filters/relativize_paths_in_css.rb +0 -16
  85. data/lib/nanoc/filters/relativize_paths_in_html.rb +0 -16
  86. data/lib/nanoc/filters/rubypants.rb +0 -14
  87. data/lib/nanoc/filters/sass.rb +0 -18
  88. data/lib/nanoc/helpers.rb +0 -9
  89. data/lib/nanoc/helpers/blogging.rb +0 -217
  90. data/lib/nanoc/helpers/capturing.rb +0 -63
  91. data/lib/nanoc/helpers/filtering.rb +0 -54
  92. data/lib/nanoc/helpers/html_escape.rb +0 -25
  93. data/lib/nanoc/helpers/link_to.rb +0 -113
  94. data/lib/nanoc/helpers/render.rb +0 -49
  95. data/lib/nanoc/helpers/tagging.rb +0 -56
  96. data/lib/nanoc/helpers/text.rb +0 -38
  97. data/lib/nanoc/helpers/xml_sitemap.rb +0 -63
  98. data/lib/nanoc/routers.rb +0 -3
  99. data/lib/nanoc/routers/default.rb +0 -54
  100. data/lib/nanoc/routers/no_dirs.rb +0 -66
  101. data/lib/nanoc/routers/versioned.rb +0 -79
  102. data/vendor/cri/ChangeLog +0 -0
  103. data/vendor/cri/LICENSE +0 -19
  104. data/vendor/cri/NEWS +0 -0
  105. data/vendor/cri/README +0 -4
  106. data/vendor/cri/Rakefile +0 -25
  107. data/vendor/cri/lib/cri.rb +0 -12
  108. data/vendor/cri/lib/cri/base.rb +0 -153
  109. data/vendor/cri/lib/cri/command.rb +0 -104
  110. data/vendor/cri/lib/cri/core_ext.rb +0 -8
  111. data/vendor/cri/lib/cri/core_ext/string.rb +0 -41
  112. data/vendor/cri/lib/cri/option_parser.rb +0 -186
  113. data/vendor/cri/test/test_base.rb +0 -6
  114. data/vendor/cri/test/test_command.rb +0 -6
  115. data/vendor/cri/test/test_core_ext.rb +0 -21
  116. data/vendor/cri/test/test_option_parser.rb +0 -279
@@ -1,72 +0,0 @@
1
- require 'singleton'
2
-
3
- module Nanoc::CLI
4
-
5
- # Nanoc::CLI::Logger is a singleton class responsible for generating
6
- # feedback in the terminal.
7
- class Logger
8
-
9
- ACTION_COLORS = {
10
- :create => "\e[1m" + "\e[32m", # bold + green
11
- :update => "\e[1m" + "\e[33m", # bold + yellow
12
- :identical => "\e[1m", # bold
13
- :skip => "\e[1m", # bold
14
- :'not written' => "\e[1m" # bold
15
- }
16
-
17
- include Singleton
18
-
19
- # The log level, which can be :high, :low or :off (which will log all
20
- # messages, only high-priority messages, or no messages at all,
21
- # respectively).
22
- attr_accessor :level
23
-
24
- # Whether to use color in log messages or not
25
- attr_accessor :color
26
- alias_method :color?, :color
27
-
28
- def initialize # :nodoc:
29
- @level = :high
30
- @color = true
31
- end
32
-
33
- # Logs a file-related action.
34
- #
35
- # +level+:: The importance of this action. Can be :high or :low.
36
- #
37
- # +action+:: The kind of file action. Can be :create, :update or
38
- # :identical.
39
- #
40
- # +path+:: The path to the file the action was performed on.
41
- def file(level, action, path, duration=nil)
42
- log(
43
- level,
44
- '%s%12s%s %s%s' % [
45
- color? ? ACTION_COLORS[action.to_sym] : '',
46
- action,
47
- color? ? "\e[0m" : '',
48
- duration.nil? ? '' : "[%2.2fs] " % [ duration ],
49
- path
50
- ]
51
- )
52
- end
53
-
54
- # Logs a message.
55
- #
56
- # +level+:: The importance of this message. Can be :high or :low.
57
- #
58
- # +s+:: The message to be logged.
59
- #
60
- # +io+:: The IO instance to which the message will be written. Defaults to
61
- # standard output.
62
- def log(level, s, io=$stdout)
63
- # Don't log when logging is disabled
64
- return if @level == :off
65
-
66
- # Log when level permits it
67
- io.puts(s) if (@level == :low or @level == level)
68
- end
69
-
70
- end
71
-
72
- end
@@ -1,2 +0,0 @@
1
- require 'nanoc/data_sources/filesystem'
2
- require 'nanoc/data_sources/filesystem_combined'
@@ -1,707 +0,0 @@
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'
77
-
78
- ########## Attributes ##########
79
-
80
- identifier :filesystem
81
-
82
- ########## VCSes ##########
83
-
84
- attr_accessor :vcs
85
-
86
- def vcs
87
- @vcs ||= Nanoc::Extra::VCSes::Dummy.new
88
- end
89
-
90
- ########## Preparation ##########
91
-
92
- def up # :nodoc:
93
- end
94
-
95
- def down # :nodoc:
96
- end
97
-
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)
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_templates
124
- end
125
-
126
- ########## Pages ##########
127
-
128
- def pages # :nodoc:
129
- meta_filenames('content').map do |meta_filename|
130
- # Read metadata
131
- meta = YAML.load_file(meta_filename) || {}
132
-
133
- if meta['is_draft']
134
- # Skip drafts
135
- nil
136
- else
137
- # Get content
138
- content_filename = content_filename_for_dir(File.dirname(meta_filename))
139
- content = File.read(content_filename)
140
-
141
- # Get attributes
142
- attributes = meta.merge(:file => Nanoc::Extra::FileProxy.new(content_filename))
143
-
144
- # Get path
145
- path = meta_filename.sub(/^content/, '').sub(/[^\/]+\.yaml$/, '')
146
-
147
- # Get modification times
148
- meta_mtime = File.stat(meta_filename).mtime
149
- content_mtime = File.stat(content_filename).mtime
150
- mtime = meta_mtime > content_mtime ? meta_mtime : content_mtime
151
-
152
- # Create page object
153
- Nanoc::Page.new(content, attributes, path, mtime)
154
- end
155
- end.compact
156
- end
157
-
158
- def save_page(page) # :nodoc:
159
- # Determine possible meta file paths
160
- last_component = page.path.split('/')[-1]
161
- meta_filename_worst = 'content' + page.path + 'index.yaml'
162
- meta_filename_best = 'content' + page.path + (last_component || 'content') + '.yaml'
163
-
164
- # Get existing path
165
- existing_path = nil
166
- existing_path = meta_filename_best if File.file?(meta_filename_best)
167
- existing_path = meta_filename_worst if File.file?(meta_filename_worst)
168
-
169
- if existing_path.nil?
170
- # Get filenames
171
- dir_path = 'content' + page.path
172
- meta_filename = meta_filename_best
173
- content_filename = 'content' + page.path + (last_component || 'content') + '.html'
174
-
175
- # Notify
176
- Nanoc::NotificationCenter.post(:file_created, meta_filename)
177
- Nanoc::NotificationCenter.post(:file_created, content_filename)
178
-
179
- # Create directories if necessary
180
- FileUtils.mkdir_p(dir_path)
181
- else
182
- # Get filenames
183
- meta_filename = existing_path
184
- content_filename = content_filename_for_dir(File.dirname(existing_path))
185
-
186
- # Notify
187
- Nanoc::NotificationCenter.post(:file_updated, meta_filename)
188
- Nanoc::NotificationCenter.post(:file_updated, content_filename)
189
- end
190
-
191
- # Write files
192
- File.open(meta_filename, 'w') { |io| io.write(page.attributes.to_split_yaml) }
193
- File.open(content_filename, 'w') { |io| io.write(page.content) }
194
-
195
- # Add to working copy if possible
196
- if existing_path.nil?
197
- vcs.add(meta_filename)
198
- vcs.add(content_filename)
199
- end
200
- end
201
-
202
- def move_page(page, new_path) # :nodoc:
203
- # TODO implement
204
- end
205
-
206
- def delete_page(page) # :nodoc:
207
- # TODO implement
208
- end
209
-
210
- ########## Assets ##########
211
-
212
- def assets # :nodoc:
213
- meta_filenames('assets').map do |meta_filename|
214
- # Read metadata
215
- meta = YAML.load_file(meta_filename) || {}
216
-
217
- # Get content file
218
- content_filename = content_filename_for_dir(File.dirname(meta_filename))
219
- content_file = Nanoc::Extra::FileProxy.new(content_filename)
220
-
221
- # Get attributes
222
- attributes = { 'extension' => File.extname(content_filename)[1..-1] }.merge(meta)
223
-
224
- # Get path
225
- path = meta_filename.sub(/^assets/, '').sub(/[^\/]+\.yaml$/, '')
226
-
227
- # Get modification times
228
- meta_mtime = File.stat(meta_filename).mtime
229
- content_mtime = File.stat(content_filename).mtime
230
- mtime = meta_mtime > content_mtime ? meta_mtime : content_mtime
231
-
232
- # Create asset object
233
- Nanoc::Asset.new(content_file, attributes, path, mtime)
234
- end
235
- end
236
-
237
- def save_asset(asset) # :nodoc:
238
- # Determine meta file path
239
- last_component = asset.path.split('/')[-1]
240
- meta_filename = 'assets' + asset.path + last_component + '.yaml'
241
-
242
- # Get existing path
243
- existing_path = nil
244
- existing_path = meta_filename_best if File.file?(meta_filename_best)
245
- existing_path = meta_filename_worst if File.file?(meta_filename_worst)
246
-
247
- if meta_filename.nil?
248
- # Get filenames
249
- dir_path = 'assets' + asset.path
250
- content_filename = 'assets' + asset.path + last_component + '.dat'
251
-
252
- # Notify
253
- Nanoc::NotificationCenter.post(:file_created, meta_filename)
254
- Nanoc::NotificationCenter.post(:file_created, content_filename)
255
-
256
- # Create directories if necessary
257
- FileUtils.mkdir_p(dir_path)
258
- else
259
- # Get filenames
260
- content_filename = content_filename_for_dir(File.dirname(meta_filename))
261
-
262
- # Notify
263
- Nanoc::NotificationCenter.post(:file_updated, meta_filename)
264
- Nanoc::NotificationCenter.post(:file_updated, content_filename)
265
- end
266
-
267
- # Write files
268
- File.open(meta_filename, 'w') { |io| io.write(asset.attributes.to_split_yaml) }
269
- File.open(content_filename, 'w') { }
270
-
271
- # Add to working copy if possible
272
- if meta_filename.nil?
273
- vcs.add(meta_filename)
274
- vcs.add(content_filename)
275
- end
276
- end
277
-
278
- def move_asset(asset, new_path) # :nodoc:
279
- # TODO implement
280
- end
281
-
282
- def delete_asset(asset) # :nodoc:
283
- # TODO implement
284
- end
285
-
286
- ########## Page Defaults ##########
287
-
288
- def page_defaults # :nodoc:
289
- # Get attributes
290
- filename = File.file?(PAGE_DEFAULTS_FILENAME) ? PAGE_DEFAULTS_FILENAME : PAGE_DEFAULTS_FILENAME_OLD
291
- attributes = YAML.load_file(filename) || {}
292
-
293
- # Get mtime
294
- mtime = File.stat(filename).mtime
295
-
296
- # Build page defaults
297
- Nanoc::PageDefaults.new(attributes, mtime)
298
- end
299
-
300
- def save_page_defaults(page_defaults) # :nodoc:
301
- # Notify
302
- if File.file?(PAGE_DEFAULTS_FILENAME)
303
- filename = PAGE_DEFAULTS_FILENAME
304
- created = false
305
- Nanoc::NotificationCenter.post(:file_updated, filename)
306
- elsif File.file?(PAGE_DEFAULTS_FILENAME_OLD)
307
- filename = PAGE_DEFAULTS_FILENAME_OLD
308
- created = false
309
- Nanoc::NotificationCenter.post(:file_updated, filename)
310
- else
311
- filename = PAGE_DEFAULTS_FILENAME
312
- created = true
313
- Nanoc::NotificationCenter.post(:file_created, filename)
314
- end
315
-
316
- # Write
317
- File.open(filename, 'w') do |io|
318
- io.write(page_defaults.attributes.to_split_yaml)
319
- end
320
-
321
- # Add to working copy if possible
322
- vcs.add(filename) if created
323
- end
324
-
325
- ########## Asset Defaults ##########
326
-
327
- def asset_defaults # :nodoc:
328
- if File.file?(ASSET_DEFAULTS_FILENAME)
329
- # Get attributes
330
- attributes = YAML.load_file(ASSET_DEFAULTS_FILENAME) || {}
331
-
332
- # Get mtime
333
- mtime = File.stat(ASSET_DEFAULTS_FILENAME).mtime
334
-
335
- # Build asset defaults
336
- Nanoc::AssetDefaults.new(attributes, mtime)
337
- else
338
- Nanoc::AssetDefaults.new({})
339
- end
340
- end
341
-
342
- def save_asset_defaults(asset_defaults) # :nodoc:
343
- # Notify
344
- if File.file?(ASSET_DEFAULTS_FILENAME)
345
- Nanoc::NotificationCenter.post(:file_updated, ASSET_DEFAULTS_FILENAME)
346
- created = false
347
- else
348
- Nanoc::NotificationCenter.post(:file_created, ASSET_DEFAULTS_FILENAME)
349
- created = true
350
- end
351
-
352
- # Write
353
- File.open(ASSET_DEFAULTS_FILENAME, 'w') do |io|
354
- io.write(asset_defaults.attributes.to_split_yaml)
355
- end
356
-
357
- # Add to working copy if possible
358
- vcs.add(ASSET_DEFAULTS_FILENAME) if created
359
- end
360
-
361
- ########## Layouts ##########
362
-
363
- def layouts # :nodoc:
364
- # Determine what layout directory structure is being used
365
- is_old_school = (Dir['layouts/*'].select { |f| File.file?(f) }.size > 0)
366
-
367
- if is_old_school
368
- # Warn about deprecation
369
- warn(
370
- 'DEPRECATION WARNING: nanoc 2.1 changes the way layouts are ' +
371
- 'stored. Future versions will not support these outdated sites. ' +
372
- 'To update your site, issue \'nanoc update\'.'
373
- )
374
-
375
- Dir[File.join('layouts', '*')].reject { |f| f =~ /~$/ }.map do |filename|
376
- # Get content
377
- content = File.read(filename)
378
-
379
- # Get attributes
380
- attributes = { :extension => File.extname(filename)}
381
-
382
- # Get path
383
- path = File.basename(filename, attributes[:extension])
384
-
385
- # Get modification time
386
- mtime = File.stat(filename).mtime
387
-
388
- # Create layout object
389
- Nanoc::Layout.new(content, attributes, path, mtime)
390
- end
391
- else
392
- meta_filenames('layouts').map do |meta_filename|
393
- # Get content
394
- content_filename = content_filename_for_dir(File.dirname(meta_filename))
395
- content = File.read(content_filename)
396
-
397
- # Get attributes
398
- attributes = YAML.load_file(meta_filename) || {}
399
-
400
- # Get path
401
- path = meta_filename.sub(/^layouts\//, '').sub(/\/[^\/]+\.yaml$/, '')
402
-
403
- # Get modification times
404
- meta_mtime = File.stat(meta_filename).mtime
405
- content_mtime = File.stat(content_filename).mtime
406
- mtime = meta_mtime > content_mtime ? meta_mtime : content_mtime
407
-
408
- # Create layout object
409
- Nanoc::Layout.new(content, attributes, path, mtime)
410
- end
411
- end
412
- end
413
-
414
- def save_layout(layout) # :nodoc:
415
- # Determine what layout directory structure is being used
416
- is_old_school = (Dir['layouts/*'].select { |f| File.file?(f) }.size > 0)
417
- error_outdated if is_old_school
418
-
419
- # Get paths
420
- last_component = layout.path.split('/')[-1]
421
- dir_path = 'layouts' + layout.path
422
- meta_filename = dir_path + last_component + '.yaml'
423
- content_filename = Dir[dir_path + last_component + '.*'][0]
424
-
425
- if File.file?(meta_filename)
426
- created = false
427
-
428
- # Notify
429
- Nanoc::NotificationCenter.post(:file_updated, meta_filename)
430
- Nanoc::NotificationCenter.post(:file_updated, content_filename)
431
- else
432
- created = true
433
-
434
- # Create dir
435
- FileUtils.mkdir_p(dir_path)
436
-
437
- # Get content filename
438
- content_filename = dir_path + last_component + '.html'
439
-
440
- # Notify
441
- Nanoc::NotificationCenter.post(:file_created, meta_filename)
442
- Nanoc::NotificationCenter.post(:file_created, content_filename)
443
- end
444
-
445
- # Write files
446
- File.open(meta_filename, 'w') { |io| io.write(layout.attributes.to_split_yaml) }
447
- File.open(content_filename, 'w') { |io| io.write(layout.content) }
448
-
449
- # Add to working copy if possible
450
- if created
451
- vcs.add(meta_filename)
452
- vcs.add(content_filename)
453
- end
454
- end
455
-
456
- def move_layout(layout, new_path) # :nodoc:
457
- # TODO implement
458
- end
459
-
460
- def delete_layout(layout) # :nodoc:
461
- # TODO implement
462
- end
463
-
464
- ########## Templates ##########
465
-
466
- def templates # :nodoc:
467
- meta_filenames('templates').map do |meta_filename|
468
- # Get name
469
- name = meta_filename.sub(/^templates\/(.*)\/[^\/]+\.yaml$/, '\1')
470
-
471
- # Get content
472
- content_filename = content_filename_for_dir(File.dirname(meta_filename))
473
- content = File.read(content_filename)
474
-
475
- # Get attributes
476
- attributes = YAML.load_file(meta_filename) || {}
477
-
478
- # Build template
479
- Nanoc::Template.new(content, attributes, name)
480
- end
481
- end
482
-
483
- def save_template(template) # :nodoc:
484
- # Determine possible meta file paths
485
- meta_filename_worst = 'templates/' + template.name + '/index.yaml'
486
- meta_filename_best = 'templates/' + template.name + '/' + template.name + '.yaml'
487
-
488
- # Get existing path
489
- existing_path = nil
490
- existing_path = meta_filename_best if File.file?(meta_filename_best)
491
- existing_path = meta_filename_worst if File.file?(meta_filename_worst)
492
-
493
- if existing_path.nil?
494
- # Get filenames
495
- dir_path = 'templates/' + template.name
496
- meta_filename = meta_filename_best
497
- content_filename = 'templates/' + template.name + '/' + template.name + '.html'
498
-
499
- # Notify
500
- Nanoc::NotificationCenter.post(:file_created, meta_filename)
501
- Nanoc::NotificationCenter.post(:file_created, content_filename)
502
-
503
- # Create directories if necessary
504
- FileUtils.mkdir_p(dir_path)
505
- else
506
- # Get filenames
507
- meta_filename = existing_path
508
- content_filename = content_filename_for_dir(File.dirname(existing_path))
509
-
510
- # Notify
511
- Nanoc::NotificationCenter.post(:file_updated, meta_filename)
512
- Nanoc::NotificationCenter.post(:file_updated, content_filename)
513
- end
514
-
515
- # Write files
516
- File.open(meta_filename, 'w') { |io| io.write(template.page_attributes.to_split_yaml) }
517
- File.open(content_filename, 'w') { |io| io.write(template.page_content) }
518
-
519
- # Add to working copy if possible
520
- if existing_path.nil?
521
- vcs.add(meta_filename)
522
- vcs.add(content_filename)
523
- end
524
- end
525
-
526
- def move_template(template, new_name) # :nodoc:
527
- # TODO implement
528
- end
529
-
530
- def delete_template(template) # :nodoc:
531
- # TODO implement
532
- end
533
-
534
- ########## Code ##########
535
-
536
- def code # :nodoc:
537
- # Get files
538
- filenames = Dir['lib/**/*.rb'].sort
539
-
540
- # Get data
541
- data = filenames.map { |filename| File.read(filename) + "\n" }.join('')
542
-
543
- # Get modification time
544
- mtimes = filenames.map { |filename| File.stat(filename).mtime }
545
- mtime = mtimes.inject { |memo, mtime| memo > mtime ? mtime : memo }
546
-
547
- # Build code
548
- Nanoc::Code.new(data, mtime)
549
- end
550
-
551
- def save_code(code) # :nodoc:
552
- # Check whether code existed
553
- existed = File.file?('lib/default.rb')
554
-
555
- # Remove all existing code files
556
- Dir['lib/**/*.rb'].each do |file|
557
- vcs.remove(file) unless file == 'lib/default.rb'
558
- end
559
-
560
- # Notify
561
- if existed
562
- Nanoc::NotificationCenter.post(:file_updated, 'lib/default.rb')
563
- else
564
- Nanoc::NotificationCenter.post(:file_created, 'lib/default.rb')
565
- end
566
-
567
- # Write new code
568
- File.open('lib/default.rb', 'w') do |io|
569
- io.write(code.data)
570
- end
571
-
572
- # Add to working copy if possible
573
- vcs.add('lib/default.rb') unless existed
574
- end
575
-
576
- private
577
-
578
- ########## Custom functions ##########
579
-
580
- # Returns the list of all meta files in the given base directory as well
581
- # as its subdirectories.
582
- def meta_filenames(base)
583
- # Find all possible meta file names
584
- filenames = Dir[base + '/**/*.yaml']
585
-
586
- # Filter out invalid meta files
587
- good_filenames = []
588
- bad_filenames = []
589
- filenames.each do |filename|
590
- if filename =~ /meta\.yaml$/ or filename =~ /([^\/]+)\/\1\.yaml$/
591
- good_filenames << filename
592
- else
593
- bad_filenames << filename
594
- end
595
- end
596
-
597
- # Warn about bad filenames
598
- unless bad_filenames.empty?
599
- raise RuntimeError.new(
600
- "The following files appear to be meta files, " +
601
- "but have an invalid name:\n - " +
602
- bad_filenames.join("\n - ")
603
- )
604
- end
605
-
606
- good_filenames
607
- end
608
-
609
- # Returns the filename of the content file in the given directory,
610
- # ignoring any unwanted files (files that end with '~', '.orig', '.rej' or
611
- # '.bak')
612
- def content_filename_for_dir(dir)
613
- # Find all files
614
- filename_glob_1 = dir.sub(/([^\/]+)$/, '\1/\1.*')
615
- filename_glob_2 = dir.sub(/([^\/]+)$/, '\1/index.*')
616
- filenames = (Dir[filename_glob_1] + Dir[filename_glob_2]).uniq
617
-
618
- # Reject meta files
619
- filenames.reject! { |f| f =~ /\.yaml$/ }
620
-
621
- # Reject backups
622
- filenames.reject! { |f| f =~ /(~|\.orig|\.rej|\.bak)$/ }
623
-
624
- # Make sure there is only one content file
625
- if filenames.size != 1
626
- raise RuntimeError.new(
627
- "Expected 1 content file in #{dir} but found #{filenames.size}"
628
- )
629
- end
630
-
631
- # Return content filename
632
- filenames.first
633
- end
634
-
635
- # Raises an "outdated data format" error.
636
- def error_outdated
637
- raise RuntimeError.new(
638
- 'This site\'s data is stored in an old format and must be updated. ' +
639
- 'To do so, issue the \'nanoc update\' command. For help on ' +
640
- 'updating a site\'s data, issue \'nanoc help update\'.'
641
- )
642
- end
643
-
644
- # Updated outdated page defaults (renames page defaults file)
645
- def update_page_defaults
646
- return unless File.file?(PAGE_DEFAULTS_FILENAME_OLD)
647
-
648
- vcs.move(PAGE_DEFAULTS_FILENAME_OLD, PAGE_DEFAULTS_FILENAME)
649
- end
650
-
651
- # Updates outdated pages (both content and meta file names).
652
- def update_pages
653
- # Update content files
654
- # content/foo/bar/baz/index.ext -> content/foo/bar/baz/baz.ext
655
- Dir['content/**/index.*'].select { |f| File.file?(f) }.each do |old_filename|
656
- # Determine new name
657
- if old_filename =~ /^content\/index\./
658
- new_filename = old_filename.sub(/^content\/index\./, 'content/content.')
659
- else
660
- new_filename = old_filename.sub(/([^\/]+)\/index\.([^\/]+)$/, '\1/\1.\2')
661
- end
662
-
663
- # Move
664
- vcs.move(old_filename, new_filename)
665
- end
666
-
667
- # Update meta files
668
- # content/foo/bar/baz/meta.yaml -> content/foo/bar/baz/baz.yaml
669
- Dir['content/**/meta.yaml'].select { |f| File.file?(f) }.each do |old_filename|
670
- # Determine new name
671
- if old_filename == 'content/meta.yaml'
672
- new_filename = 'content/content.yaml'
673
- else
674
- new_filename = old_filename.sub(/([^\/]+)\/meta.yaml$/, '\1/\1.yaml')
675
- end
676
-
677
- # Move
678
- vcs.move(old_filename, new_filename)
679
- end
680
- end
681
-
682
- # Updates outdated templates (both content and meta file names).
683
- def update_templates
684
- # Update content files
685
- # templates/foo/index.ext -> templates/foo/foo.ext
686
- Dir['templates/**/index.*'].select { |f| File.file?(f) }.each do |old_filename|
687
- # Determine new name
688
- new_filename = old_filename.sub(/([^\/]+)\/index\.([^\/]+)$/, '\1/\1.\2')
689
-
690
- # Move
691
- vcs.move(old_filename, new_filename)
692
- end
693
-
694
- # Update meta files
695
- # templates/foo/meta.yaml -> templates/foo/foo.yaml
696
- Dir['templates/**/meta.yaml'].select { |f| File.file?(f) }.each do |old_filename|
697
- # Determine new name
698
- new_filename = old_filename.sub(/([^\/]+)\/meta.yaml$/, '\1/\1.yaml')
699
-
700
- # Move
701
- vcs.move(old_filename, new_filename)
702
- end
703
- end
704
-
705
- end
706
-
707
- end