nanoc3 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. data/ChangeLog +3 -0
  2. data/LICENSE +19 -0
  3. data/NEWS.rdoc +262 -0
  4. data/README.rdoc +80 -0
  5. data/Rakefile +11 -0
  6. data/bin/nanoc3 +16 -0
  7. data/lib/nanoc3/base/code_snippet.rb +42 -0
  8. data/lib/nanoc3/base/compiler.rb +225 -0
  9. data/lib/nanoc3/base/compiler_dsl.rb +110 -0
  10. data/lib/nanoc3/base/core_ext/array.rb +21 -0
  11. data/lib/nanoc3/base/core_ext/hash.rb +23 -0
  12. data/lib/nanoc3/base/core_ext/string.rb +14 -0
  13. data/lib/nanoc3/base/core_ext.rb +5 -0
  14. data/lib/nanoc3/base/data_source.rb +197 -0
  15. data/lib/nanoc3/base/dependency_tracker.rb +291 -0
  16. data/lib/nanoc3/base/errors.rb +95 -0
  17. data/lib/nanoc3/base/filter.rb +60 -0
  18. data/lib/nanoc3/base/item.rb +87 -0
  19. data/lib/nanoc3/base/item_rep.rb +236 -0
  20. data/lib/nanoc3/base/layout.rb +53 -0
  21. data/lib/nanoc3/base/notification_center.rb +68 -0
  22. data/lib/nanoc3/base/plugin.rb +88 -0
  23. data/lib/nanoc3/base/preprocessor_context.rb +37 -0
  24. data/lib/nanoc3/base/rule.rb +37 -0
  25. data/lib/nanoc3/base/rule_context.rb +68 -0
  26. data/lib/nanoc3/base/site.rb +334 -0
  27. data/lib/nanoc3/base.rb +25 -0
  28. data/lib/nanoc3/cli/base.rb +151 -0
  29. data/lib/nanoc3/cli/commands/autocompile.rb +89 -0
  30. data/lib/nanoc3/cli/commands/compile.rb +279 -0
  31. data/lib/nanoc3/cli/commands/create_item.rb +79 -0
  32. data/lib/nanoc3/cli/commands/create_layout.rb +94 -0
  33. data/lib/nanoc3/cli/commands/create_site.rb +320 -0
  34. data/lib/nanoc3/cli/commands/help.rb +71 -0
  35. data/lib/nanoc3/cli/commands/info.rb +114 -0
  36. data/lib/nanoc3/cli/commands/update.rb +96 -0
  37. data/lib/nanoc3/cli/commands.rb +13 -0
  38. data/lib/nanoc3/cli/logger.rb +73 -0
  39. data/lib/nanoc3/cli.rb +16 -0
  40. data/lib/nanoc3/data_sources/delicious.rb +66 -0
  41. data/lib/nanoc3/data_sources/filesystem.rb +231 -0
  42. data/lib/nanoc3/data_sources/filesystem_combined.rb +202 -0
  43. data/lib/nanoc3/data_sources/filesystem_common.rb +22 -0
  44. data/lib/nanoc3/data_sources/filesystem_compact.rb +232 -0
  45. data/lib/nanoc3/data_sources/last_fm.rb +103 -0
  46. data/lib/nanoc3/data_sources/twitter.rb +53 -0
  47. data/lib/nanoc3/data_sources.rb +20 -0
  48. data/lib/nanoc3/extra/auto_compiler.rb +97 -0
  49. data/lib/nanoc3/extra/chick.rb +119 -0
  50. data/lib/nanoc3/extra/context.rb +24 -0
  51. data/lib/nanoc3/extra/core_ext/time.rb +19 -0
  52. data/lib/nanoc3/extra/core_ext.rb +3 -0
  53. data/lib/nanoc3/extra/deployers/rsync.rb +64 -0
  54. data/lib/nanoc3/extra/deployers.rb +12 -0
  55. data/lib/nanoc3/extra/file_proxy.rb +31 -0
  56. data/lib/nanoc3/extra/validators/links.rb +0 -0
  57. data/lib/nanoc3/extra/validators/w3c.rb +71 -0
  58. data/lib/nanoc3/extra/validators.rb +12 -0
  59. data/lib/nanoc3/extra/vcs.rb +65 -0
  60. data/lib/nanoc3/extra/vcses/bazaar.rb +21 -0
  61. data/lib/nanoc3/extra/vcses/dummy.rb +20 -0
  62. data/lib/nanoc3/extra/vcses/git.rb +21 -0
  63. data/lib/nanoc3/extra/vcses/mercurial.rb +21 -0
  64. data/lib/nanoc3/extra/vcses/subversion.rb +21 -0
  65. data/lib/nanoc3/extra/vcses.rb +17 -0
  66. data/lib/nanoc3/extra.rb +16 -0
  67. data/lib/nanoc3/filters/bluecloth.rb +13 -0
  68. data/lib/nanoc3/filters/coderay.rb +17 -0
  69. data/lib/nanoc3/filters/erb.rb +19 -0
  70. data/lib/nanoc3/filters/erubis.rb +17 -0
  71. data/lib/nanoc3/filters/haml.rb +20 -0
  72. data/lib/nanoc3/filters/less.rb +13 -0
  73. data/lib/nanoc3/filters/markaby.rb +14 -0
  74. data/lib/nanoc3/filters/maruku.rb +14 -0
  75. data/lib/nanoc3/filters/rainpress.rb +13 -0
  76. data/lib/nanoc3/filters/rdiscount.rb +13 -0
  77. data/lib/nanoc3/filters/rdoc.rb +23 -0
  78. data/lib/nanoc3/filters/redcloth.rb +14 -0
  79. data/lib/nanoc3/filters/relativize_paths.rb +32 -0
  80. data/lib/nanoc3/filters/rubypants.rb +14 -0
  81. data/lib/nanoc3/filters/sass.rb +17 -0
  82. data/lib/nanoc3/filters.rb +37 -0
  83. data/lib/nanoc3/helpers/blogging.rb +226 -0
  84. data/lib/nanoc3/helpers/breadcrumbs.rb +25 -0
  85. data/lib/nanoc3/helpers/capturing.rb +71 -0
  86. data/lib/nanoc3/helpers/filtering.rb +46 -0
  87. data/lib/nanoc3/helpers/html_escape.rb +22 -0
  88. data/lib/nanoc3/helpers/link_to.rb +120 -0
  89. data/lib/nanoc3/helpers/rendering.rb +76 -0
  90. data/lib/nanoc3/helpers/tagging.rb +58 -0
  91. data/lib/nanoc3/helpers/text.rb +40 -0
  92. data/lib/nanoc3/helpers/xml_sitemap.rb +69 -0
  93. data/lib/nanoc3/helpers.rb +16 -0
  94. data/lib/nanoc3/package.rb +106 -0
  95. data/lib/nanoc3/tasks/clean.rake +16 -0
  96. data/lib/nanoc3/tasks/clean.rb +33 -0
  97. data/lib/nanoc3/tasks/deploy/rsync.rake +11 -0
  98. data/lib/nanoc3/tasks/validate.rake +35 -0
  99. data/lib/nanoc3/tasks.rb +9 -0
  100. data/lib/nanoc3.rb +19 -0
  101. data/vendor/cri/ChangeLog +0 -0
  102. data/vendor/cri/LICENSE +19 -0
  103. data/vendor/cri/NEWS +0 -0
  104. data/vendor/cri/README +4 -0
  105. data/vendor/cri/Rakefile +25 -0
  106. data/vendor/cri/lib/cri/base.rb +153 -0
  107. data/vendor/cri/lib/cri/command.rb +105 -0
  108. data/vendor/cri/lib/cri/core_ext/string.rb +41 -0
  109. data/vendor/cri/lib/cri/core_ext.rb +8 -0
  110. data/vendor/cri/lib/cri/option_parser.rb +186 -0
  111. data/vendor/cri/lib/cri.rb +12 -0
  112. data/vendor/cri/test/test_base.rb +6 -0
  113. data/vendor/cri/test/test_command.rb +6 -0
  114. data/vendor/cri/test/test_core_ext.rb +21 -0
  115. data/vendor/cri/test/test_option_parser.rb +279 -0
  116. metadata +225 -0
@@ -0,0 +1,37 @@
1
+ module Nanoc3
2
+
3
+ # Nanoc3::PreprocessorContext provides a context in which preprocessing code
4
+ # can be executed. It provides access to the site and its configuration,
5
+ # items and layouts.
6
+ class PreprocessorContext
7
+
8
+ # Creates a new preprocessor context for the given site.
9
+ def initialize(site)
10
+ @site = site
11
+ end
12
+
13
+ # The site for which the preprocessor code is being executed.
14
+ def site
15
+ @site
16
+ end
17
+
18
+ # The configuration of the site for which the preprocessor code is being
19
+ # executed.
20
+ def config
21
+ site.config
22
+ end
23
+
24
+ # The items in the site for which the preprocessor code is being executed.
25
+ def items
26
+ site.items
27
+ end
28
+
29
+ # The layouts in the site for which the preprocessor code is being
30
+ # executed.
31
+ def layouts
32
+ site.layouts
33
+ end
34
+
35
+ end
36
+
37
+ end
@@ -0,0 +1,37 @@
1
+ # encoding: utf-8
2
+
3
+ module Nanoc3
4
+
5
+ # Nanoc3::Rule contains the processing information for a item.
6
+ class Rule
7
+
8
+ # The regex that determines which items this rule can be applied to. This
9
+ # rule can be applied to items with a identifier matching this regex.
10
+ attr_reader :identifier_regex
11
+
12
+ # The name of the representation that will be compiled using this rule.
13
+ attr_reader :rep_name
14
+
15
+ # Creates a new item compilation rule with the given identifier regex, compiler
16
+ # and block. The block will be called during compilation with the item rep
17
+ # as its argument.
18
+ def initialize(identifier_regex, rep_name, block)
19
+ @identifier_regex = identifier_regex
20
+ @rep_name = rep_name.to_sym
21
+
22
+ @block = block
23
+ end
24
+
25
+ # Returns true if this rule can be applied to the given item rep.
26
+ def applicable_to?(item)
27
+ item.identifier =~ @identifier_regex
28
+ end
29
+
30
+ # Applies this rule to the given item rep.
31
+ def apply_to(rep)
32
+ Nanoc3::RuleContext.new(rep).instance_eval &@block
33
+ end
34
+
35
+ end
36
+
37
+ end
@@ -0,0 +1,68 @@
1
+ module Nanoc3
2
+
3
+ # Nanoc3::RuleContext provides a context in which compilation and routing
4
+ # rules can be executed. It provides access to the item representation that
5
+ # is being compiled or routed.
6
+ class RuleContext
7
+
8
+ # Creates a new rule context for the given item representation.
9
+ def initialize(rep)
10
+ @rep = rep
11
+ end
12
+
13
+ # The representation that is currently being processed in this context.
14
+ def rep
15
+ @rep
16
+ end
17
+
18
+ # The item of the representation that is currently being processed in this
19
+ # context.
20
+ def item
21
+ rep.item
22
+ end
23
+
24
+ # The site of the item representation that is currently being processed in
25
+ # this context.
26
+ def site
27
+ item.site
28
+ end
29
+
30
+ # The configuration of the site of the item representation that is
31
+ # currently being processed in this context.
32
+ def config
33
+ site.config
34
+ end
35
+
36
+ # The items in the site of the item representation that is currently being
37
+ # processed in this context.
38
+ def items
39
+ site.items
40
+ end
41
+
42
+ # The layouts in the site of the item representation that is currently
43
+ # being processed in this context.
44
+ def layouts
45
+ site.layouts
46
+ end
47
+
48
+ # Filters the current representation (calls #filter with the given
49
+ # arguments on the rep).
50
+ def filter(filter_name, filter_args={})
51
+ rep.filter(filter_name, filter_args)
52
+ end
53
+
54
+ # Layouts the current representation (calls #layout with the given
55
+ # arguments on the rep).
56
+ def layout(layout_identifier)
57
+ rep.layout(layout_identifier)
58
+ end
59
+
60
+ # Creates a snapshot of the current representation (calls #snapshot with
61
+ # the given arguments on the rep).
62
+ def snapshot(snapshot_name)
63
+ rep.snapshot(snapshot_name)
64
+ end
65
+
66
+ end
67
+
68
+ end
@@ -0,0 +1,334 @@
1
+ # encoding: utf-8
2
+
3
+ module Nanoc3
4
+
5
+ # A Nanoc3::Site is the in-memory representation of a nanoc site. It holds
6
+ # references to the following site data:
7
+ #
8
+ # * +items+ is a list of Nanoc3::Item instances representing items
9
+ # * +layouts+ is a list of Nanoc3::Layout instances representing layouts
10
+ # * +code_snippets+ is list of Nanoc3::CodeSnippet instance representing
11
+ # custom site code
12
+ #
13
+ # In addition, each site has a +config+ hash which stores the site
14
+ # configuration. This configuration hash can have the following keys:
15
+ #
16
+ # +output_dir+:: The directory to which compiled items will be written. This
17
+ # path is relative to the current working directory, but can
18
+ # also be an absolute path.
19
+ #
20
+ # +data_sources+:: A list of data sources for this site. See below for
21
+ # documentation on the structure of this list. By default,
22
+ # there is only one data source of the filesystem type
23
+ # mounted at /.
24
+ #
25
+ # +index_filenames+:: A list of filenames that will be stripped off full
26
+ # item paths to create cleaner URLs (for example,
27
+ # '/about/' will be used instead of
28
+ # '/about/index.html'). The default value should be okay
29
+ # in most cases.
30
+ #
31
+ # The list of data sources consists of hashes with the following keys:
32
+ #
33
+ # +:type+:: The type of data source, i.e. its identifier.
34
+ #
35
+ # +:items_root+:: The prefix that should be given to all items returned by
36
+ # the #items method (comparable to mount points for
37
+ # filesystems in Unix-ish OSes).
38
+ #
39
+ # +:layouts_root+:: The prefix that should be given to all layouts returned
40
+ # by the #layouts method (comparable to mount points for
41
+ # filesystems in Unix-ish OSes).
42
+ #
43
+ # +:config+:: A hash containing the configuration for this data source. This
44
+ # is especially useful for online data sources; for example, a
45
+ # Twitter data source would need the username of the account
46
+ # from which to fetch tweets.
47
+ #
48
+ # A site also has several helper classes:
49
+ #
50
+ # * +data_source+ is a Nanoc3::DataSource subclass instance used for loading
51
+ # site data.
52
+ # * +compiler+ is a Nanoc3::Compiler instance that compiles item
53
+ # representations.
54
+ #
55
+ # The physical representation of a Nanoc3::Site is usually a directory that
56
+ # contains a configuration file, site data, a rakefile, a rules file, etc.
57
+ # The way site data is stored depends on the data source.
58
+ class Site
59
+
60
+ # The default configuration for a data source. A data source's
61
+ # configuration overrides these options.
62
+ DEFAULT_DATA_SOURCE_CONFIG = {
63
+ :type => 'filesystem_compact',
64
+ :items_root => '/',
65
+ :layouts_root => '/',
66
+ :config => {}
67
+ }
68
+
69
+ # The default configuration for a site. A site's configuration overrides
70
+ # these options: when a Nanoc3::Site is created with a configuration that
71
+ # lacks some options, the default value will be taken from
72
+ # +DEFAULT_CONFIG+.
73
+ DEFAULT_CONFIG = {
74
+ :output_dir => 'output',
75
+ :data_sources => [ {} ],
76
+ :index_filenames => [ 'index.html' ]
77
+ }
78
+
79
+ # The site configuration.
80
+ attr_reader :config
81
+
82
+ # The timestamp when the site configuration was last modified.
83
+ attr_reader :config_mtime
84
+
85
+ # The timestamp when the rules were last modified.
86
+ attr_reader :rules_mtime
87
+
88
+ # The code block that will be executed after all data is loaded but before
89
+ # the site is compiled.
90
+ attr_accessor :preprocessor
91
+
92
+ # Creates a Nanoc3::Site object for the site specified by the given
93
+ # +dir_or_config_hash+ argument.
94
+ #
95
+ # +dir_or_config_hash+:: If a string, contains the path to the site
96
+ # directory; if a hash, contains the site
97
+ # configuration.
98
+ def initialize(dir_or_config_hash)
99
+ build_config(dir_or_config_hash)
100
+
101
+ @code_snippets_loaded = false
102
+ @items_loaded = false
103
+ @layouts_loaded = false
104
+ end
105
+
106
+ # Returns the compiler for this site. Will create a new compiler if none
107
+ # exists yet.
108
+ def compiler
109
+ @compiler ||= Compiler.new(self)
110
+ end
111
+
112
+ # Returns the data sources for this site. Will create a new data source if
113
+ # none exists yet. Raises Nanoc3::Errors::UnknownDataSource if the site
114
+ # configuration specifies an unknown data source.
115
+ def data_sources
116
+ @data_sources ||= begin
117
+ @config[:data_sources].map do |data_source_hash|
118
+ # Get data source class
119
+ data_source_class = Nanoc3::DataSource.named(data_source_hash[:type])
120
+ raise Nanoc3::Errors::UnknownDataSource.new(data_source_hash[:type]) if data_source_class.nil?
121
+
122
+ # Create data source
123
+ data_source_class.new(
124
+ self,
125
+ data_source_hash[:items_root],
126
+ data_source_hash[:layouts_root],
127
+ data_source_hash[:config] || {}
128
+ )
129
+ end
130
+ end
131
+ end
132
+
133
+ # Loads the site data. This will query the Nanoc3::DataSource associated
134
+ # with the site and fetch all site data. The site data is cached, so
135
+ # calling this method will not have any effect the second time, unless
136
+ # +force+ is true.
137
+ #
138
+ # +force+:: If true, will force load the site data even if it has been
139
+ # loaded before, to circumvent caching issues.
140
+ def load_data(force=false)
141
+ # Don't load data twice
142
+ return if instance_variable_defined?(:@data_loaded) && @data_loaded && !force
143
+
144
+ # Load all data
145
+ data_sources.each { |ds| ds.use }
146
+ load_code_snippets(force)
147
+ load_rules
148
+ load_items
149
+ load_layouts
150
+ data_sources.each { |ds| ds.unuse }
151
+
152
+ # Preprocess
153
+ setup_child_parent_links
154
+ Nanoc3::PreprocessorContext.new(self).instance_eval(&preprocessor) unless preprocessor.nil?
155
+ link_everything_to_site
156
+ setup_child_parent_links
157
+ build_reps
158
+ route_reps
159
+
160
+ # Done
161
+ @data_loaded = true
162
+ end
163
+
164
+ # Returns this site's code snippets. Raises an exception if data hasn't been loaded yet.
165
+ def code_snippets
166
+ raise Nanoc3::Errors::DataNotYetAvailable.new('Code snippets', false) unless @code_snippets_loaded
167
+ @code_snippets
168
+ end
169
+
170
+ # Returns this site's items. Raises an exception if data hasn't been loaded yet.
171
+ def items
172
+ raise Nanoc3::Errors::DataNotYetAvailable.new('Items', true) unless @items_loaded
173
+ @items
174
+ end
175
+
176
+ # Returns this site's layouts. Raises an exception if data hasn't been loaded yet.
177
+ def layouts
178
+ raise Nanoc3::Errors::DataNotYetAvailable.new('Layouts', true) unless @layouts_loaded
179
+ @layouts
180
+ end
181
+
182
+ private
183
+
184
+ # Returns the Nanoc3::CompilerDSL that should be used for this site.
185
+ def dsl
186
+ @dsl ||= Nanoc3::CompilerDSL.new(self)
187
+ end
188
+
189
+ # Loads this site's code and executes it.
190
+ def load_code_snippets(force=false)
191
+ # Don't load code snippets twice
192
+ return if @code_snippets_loaded and !force
193
+
194
+ # Get code snippets
195
+ @code_snippets = data_sources.map { |ds| ds.code_snippets }.flatten
196
+
197
+ # Execute code snippets
198
+ @code_snippets.each { |cs| cs.load }
199
+
200
+ @code_snippets_loaded = true
201
+ end
202
+
203
+ # Loads this site's rules.
204
+ def load_rules
205
+ # Find rules file
206
+ rules_filename = [ 'Rules', 'rules', 'Rules.rb', 'rules.rb' ].find { |f| File.file?(f) }
207
+ raise Nanoc3::Errors::NoRulesFileFound.new if rules_filename.nil?
208
+
209
+ # Get rule data
210
+ @rules = File.read(rules_filename)
211
+ @rules_mtime = File.stat(rules_filename).mtime
212
+
213
+ # Load DSL
214
+ dsl.instance_eval(@rules)
215
+ end
216
+
217
+ # Loads this site's items, sets up item child-parent relationships and
218
+ # builds each item's list of item representations.
219
+ def load_items
220
+ @items = []
221
+ data_sources.each do |ds|
222
+ items_in_ds = ds.items
223
+ items_in_ds.each { |i| i.identifier = File.join(ds.items_root, i.identifier) }
224
+ @items += items_in_ds
225
+ end
226
+
227
+ @items_loaded = true
228
+ end
229
+
230
+ # Loads this site's layouts.
231
+ def load_layouts
232
+ @layouts = []
233
+ data_sources.each do |ds|
234
+ layouts_in_ds = ds.layouts
235
+ layouts_in_ds.each { |i| i.identifier = File.join(ds.layouts_root, i.identifier) }
236
+ @layouts += layouts_in_ds
237
+ end
238
+
239
+ @layouts_loaded = true
240
+ end
241
+
242
+ # Links items, layouts and code snippets to the site.
243
+ def link_everything_to_site
244
+ @items.each { |i| i.site = self }
245
+ @layouts.each { |l| l.site = self }
246
+ @code_snippets.each { |cs| cs.site = self }
247
+ end
248
+
249
+ # Fills each item's parent reference and children array with the
250
+ # appropriate items.
251
+ def setup_child_parent_links
252
+ # Clear all links
253
+ @items.each do |item|
254
+ item.parent = nil
255
+ item.children = []
256
+ end
257
+
258
+ @items.each do |item|
259
+ # Get parent
260
+ parent_identifier = item.identifier.sub(/[^\/]+\/$/, '')
261
+ parent = @items.find { |p| p.identifier == parent_identifier }
262
+ next if parent.nil? or item.identifier == '/'
263
+
264
+ # Link
265
+ item.parent = parent
266
+ parent.children << item
267
+ end
268
+ end
269
+
270
+ # Creates the representations of all items as defined by the compilation
271
+ # rules.
272
+ def build_reps
273
+ @items.each do |item|
274
+ # Find matching rules
275
+ matching_rules = self.compiler.item_compilation_rules.select { |r| r.applicable_to?(item) }
276
+ raise Nanoc3::Errors::NoMatchingCompilationRuleFound.new(rep) if matching_rules.empty?
277
+
278
+ # Create reps
279
+ rep_names = matching_rules.map { |r| r.rep_name }.uniq
280
+ rep_names.each do |rep_name|
281
+ item.reps << ItemRep.new(item, rep_name)
282
+ end
283
+ end
284
+ end
285
+
286
+ # Determines the paths of all item representations.
287
+ def route_reps
288
+ reps = @items.map { |i| i.reps }.flatten
289
+ reps.each do |rep|
290
+ # Find matching rule
291
+ rule = self.compiler.routing_rule_for(rep)
292
+ raise Nanoc3::Errors::NoMatchingRoutingRuleFound.new(rep) if rule.nil?
293
+
294
+ # Get basic path by applying matching rule
295
+ basic_path = rule.apply_to(rep)
296
+ next if basic_path.nil?
297
+
298
+ # Get raw path by prepending output directory
299
+ rep.raw_path = self.config[:output_dir] + basic_path
300
+
301
+ # Get normal path by stripping index filename
302
+ rep.path = basic_path
303
+ self.config[:index_filenames].each do |index_filename|
304
+ if rep.path[-index_filename.length..-1] == index_filename
305
+ # Strip and stop
306
+ rep.path = rep.path[0..-index_filename.length-1]
307
+ break
308
+ end
309
+ end
310
+ end
311
+ end
312
+
313
+ # Builds the configuration hash based on the given argument. Also see
314
+ # #initialize for details.
315
+ def build_config(dir_or_config_hash)
316
+ if dir_or_config_hash.is_a? String
317
+ # Read config from config.yaml in given dir
318
+ config_path = File.join(dir_or_config_hash, 'config.yaml')
319
+ @config = DEFAULT_CONFIG.merge(YAML.load_file(config_path).symbolize_keys)
320
+ @config[:data_sources].map! { |ds| ds.symbolize_keys }
321
+ @config_mtime = File.stat(config_path).mtime
322
+ else
323
+ # Use passed config hash
324
+ @config = DEFAULT_CONFIG.merge(dir_or_config_hash)
325
+ @config_mtime = nil
326
+ end
327
+
328
+ # Merge data sources with default data source config
329
+ @config[:data_sources].map! { |ds| DEFAULT_DATA_SOURCE_CONFIG.merge(ds) }
330
+ end
331
+
332
+ end
333
+
334
+ end
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+
3
+ module Nanoc3
4
+
5
+ require 'nanoc3/base/core_ext'
6
+
7
+ autoload 'CodeSnippet', 'nanoc3/base/code_snippet'
8
+ autoload 'Compiler', 'nanoc3/base/compiler'
9
+ autoload 'CompilerDSL', 'nanoc3/base/compiler_dsl'
10
+ autoload 'Config', 'nanoc3/base/config'
11
+ autoload 'DataSource', 'nanoc3/base/data_source'
12
+ autoload 'DependencyTracker', 'nanoc3/base/dependency_tracker'
13
+ autoload 'Errors', 'nanoc3/base/errors'
14
+ autoload 'Filter', 'nanoc3/base/filter'
15
+ autoload 'Item', 'nanoc3/base/item'
16
+ autoload 'ItemRep', 'nanoc3/base/item_rep'
17
+ autoload 'Layout', 'nanoc3/base/layout'
18
+ autoload 'NotificationCenter', 'nanoc3/base/notification_center'
19
+ autoload 'Plugin', 'nanoc3/base/plugin'
20
+ autoload 'PreprocessorContext', 'nanoc3/base/preprocessor_context'
21
+ autoload 'Rule', 'nanoc3/base/rule'
22
+ autoload 'RuleContext', 'nanoc3/base/rule_context'
23
+ autoload 'Site', 'nanoc3/base/site'
24
+
25
+ end
@@ -0,0 +1,151 @@
1
+ # encoding: utf-8
2
+
3
+ module Nanoc3::CLI
4
+
5
+ class Base < Cri::Base
6
+
7
+ def initialize
8
+ super('nanoc3')
9
+
10
+ # Add help command
11
+ self.help_command = Nanoc3::CLI::Commands::Help.new
12
+ add_command(self.help_command)
13
+
14
+ # Add other commands
15
+ add_command(Nanoc3::CLI::Commands::Autocompile.new)
16
+ add_command(Nanoc3::CLI::Commands::Compile.new)
17
+ add_command(Nanoc3::CLI::Commands::CreateLayout.new)
18
+ add_command(Nanoc3::CLI::Commands::CreateItem.new)
19
+ add_command(Nanoc3::CLI::Commands::CreateSite.new)
20
+ add_command(Nanoc3::CLI::Commands::Info.new)
21
+ add_command(Nanoc3::CLI::Commands::Update.new)
22
+ end
23
+
24
+ def self.shared_base
25
+ @shared_base ||= Nanoc3::CLI::Base.new
26
+ end
27
+
28
+ # Helper function which can be called when a command is executed that
29
+ # requires a site, such as the compile command.
30
+ def require_site
31
+ if site.nil?
32
+ $stderr.puts 'The current working directory does not seem to be a ' +
33
+ 'valid/complete nanoc site directory; aborting.'
34
+ exit 1
35
+ end
36
+ end
37
+
38
+ # Gets the site (Nanoc3::Site) in the current directory and loads its data.
39
+ def site
40
+ # Load site if possible
41
+ if File.file?('config.yaml') && (!self.instance_variable_defined?(:@site) || @site.nil?)
42
+ begin
43
+ @site = Nanoc3::Site.new('.')
44
+ rescue Nanoc3::Errors::UnknownDataSource => e
45
+ $stderr.puts "Unknown data source: #{e}"
46
+ exit 1
47
+ rescue StandardError, ScriptError => error
48
+ # Header
49
+ $stderr.puts '+--- /!\ ERROR /!\ -------------------------------------------+'
50
+ $stderr.puts '| An exception occured while loading the site. If you think |'
51
+ $stderr.puts '| this is a bug in nanoc, please do report it at |'
52
+ $stderr.puts '| <http://projects.stoneship.org/trac/nanoc/newticket> -- |'
53
+ $stderr.puts '| thanks in advance! |'
54
+ $stderr.puts '+-------------------------------------------------------------+'
55
+
56
+ # Exception
57
+ $stderr.puts
58
+ $stderr.puts '=== MESSAGE:'
59
+ $stderr.puts
60
+ $stderr.puts "#{error.class}: #{error.message}"
61
+
62
+ # Backtrace
63
+ require 'enumerator'
64
+ $stderr.puts
65
+ $stderr.puts '=== BACKTRACE:'
66
+ $stderr.puts
67
+ $stderr.puts error.backtrace.to_enum(:each_with_index).map { |item, index| " #{index}. #{item}" }.join("\n")
68
+
69
+ exit 1
70
+ end
71
+ end
72
+
73
+ @site
74
+ end
75
+
76
+ # Sets the data source's VCS to the VCS with the given name. Does nothing
77
+ # when the site's data source does not support VCSes (i.e. does not
78
+ # implement #vcs=).
79
+ def set_vcs(vcs_name)
80
+ # Skip if not possible
81
+ return if vcs_name.nil? || site.nil?
82
+
83
+ # Find VCS
84
+ vcs_class = Nanoc3::Extra::VCS.named(vcs_name.to_sym)
85
+ if vcs_class.nil?
86
+ $stderr.puts "A VCS named #{vcs_name} was not found; aborting."
87
+ exit 1
88
+ end
89
+
90
+ site.data_sources.each do |data_source|
91
+ # Skip if not possible
92
+ next if !data_source.respond_to?(:vcs=)
93
+
94
+ # Set VCS
95
+ data_source.vcs = vcs_class.new
96
+ end
97
+ end
98
+
99
+ # Returns the list of global option definitionss.
100
+ def global_option_definitions
101
+ [
102
+ {
103
+ :long => 'help', :short => 'h', :argument => :forbidden,
104
+ :desc => 'show this help message and quit'
105
+ },
106
+ {
107
+ :long => 'no-color', :short => 'C', :argument => :forbidden,
108
+ :desc => 'disable color'
109
+ },
110
+ {
111
+ :long => 'version', :short => 'v', :argument => :forbidden,
112
+ :desc => 'show version information and quit'
113
+ },
114
+ {
115
+ :long => 'verbose', :short => 'V', :argument => :forbidden,
116
+ :desc => 'make nanoc output more detailed'
117
+ },
118
+ {
119
+ :long => 'debug', :short => 'd', :argument => :forbidden,
120
+ :desc => 'enable debugging (set $DEBUG to true)'
121
+ },
122
+ {
123
+ :long => 'warn', :short => 'w', :argument => :forbidden,
124
+ :desc => 'enable warnings'
125
+ }
126
+ ]
127
+ end
128
+
129
+ def handle_option(option)
130
+ case option
131
+ when :version
132
+ puts "nanoc #{Nanoc3::VERSION} (c) 2007-2009 Denis Defreyne."
133
+ puts "Ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) running on #{RUBY_PLATFORM}"
134
+ exit 0
135
+ when :verbose
136
+ Nanoc3::CLI::Logger.instance.level = :low
137
+ when :debug
138
+ $DEBUG = true
139
+ when :warn
140
+ $-w = true
141
+ when :'no-color'
142
+ Nanoc3::CLI::Logger.instance.color = false
143
+ when :help
144
+ show_help
145
+ exit 0
146
+ end
147
+ end
148
+
149
+ end
150
+
151
+ end