nanoc3 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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