nanoc3 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +3 -0
- data/LICENSE +19 -0
- data/NEWS.rdoc +262 -0
- data/README.rdoc +80 -0
- data/Rakefile +11 -0
- data/bin/nanoc3 +16 -0
- data/lib/nanoc3/base/code_snippet.rb +42 -0
- data/lib/nanoc3/base/compiler.rb +225 -0
- data/lib/nanoc3/base/compiler_dsl.rb +110 -0
- data/lib/nanoc3/base/core_ext/array.rb +21 -0
- data/lib/nanoc3/base/core_ext/hash.rb +23 -0
- data/lib/nanoc3/base/core_ext/string.rb +14 -0
- data/lib/nanoc3/base/core_ext.rb +5 -0
- data/lib/nanoc3/base/data_source.rb +197 -0
- data/lib/nanoc3/base/dependency_tracker.rb +291 -0
- data/lib/nanoc3/base/errors.rb +95 -0
- data/lib/nanoc3/base/filter.rb +60 -0
- data/lib/nanoc3/base/item.rb +87 -0
- data/lib/nanoc3/base/item_rep.rb +236 -0
- data/lib/nanoc3/base/layout.rb +53 -0
- data/lib/nanoc3/base/notification_center.rb +68 -0
- data/lib/nanoc3/base/plugin.rb +88 -0
- data/lib/nanoc3/base/preprocessor_context.rb +37 -0
- data/lib/nanoc3/base/rule.rb +37 -0
- data/lib/nanoc3/base/rule_context.rb +68 -0
- data/lib/nanoc3/base/site.rb +334 -0
- data/lib/nanoc3/base.rb +25 -0
- data/lib/nanoc3/cli/base.rb +151 -0
- data/lib/nanoc3/cli/commands/autocompile.rb +89 -0
- data/lib/nanoc3/cli/commands/compile.rb +279 -0
- data/lib/nanoc3/cli/commands/create_item.rb +79 -0
- data/lib/nanoc3/cli/commands/create_layout.rb +94 -0
- data/lib/nanoc3/cli/commands/create_site.rb +320 -0
- data/lib/nanoc3/cli/commands/help.rb +71 -0
- data/lib/nanoc3/cli/commands/info.rb +114 -0
- data/lib/nanoc3/cli/commands/update.rb +96 -0
- data/lib/nanoc3/cli/commands.rb +13 -0
- data/lib/nanoc3/cli/logger.rb +73 -0
- data/lib/nanoc3/cli.rb +16 -0
- data/lib/nanoc3/data_sources/delicious.rb +66 -0
- data/lib/nanoc3/data_sources/filesystem.rb +231 -0
- data/lib/nanoc3/data_sources/filesystem_combined.rb +202 -0
- data/lib/nanoc3/data_sources/filesystem_common.rb +22 -0
- data/lib/nanoc3/data_sources/filesystem_compact.rb +232 -0
- data/lib/nanoc3/data_sources/last_fm.rb +103 -0
- data/lib/nanoc3/data_sources/twitter.rb +53 -0
- data/lib/nanoc3/data_sources.rb +20 -0
- data/lib/nanoc3/extra/auto_compiler.rb +97 -0
- data/lib/nanoc3/extra/chick.rb +119 -0
- data/lib/nanoc3/extra/context.rb +24 -0
- data/lib/nanoc3/extra/core_ext/time.rb +19 -0
- data/lib/nanoc3/extra/core_ext.rb +3 -0
- data/lib/nanoc3/extra/deployers/rsync.rb +64 -0
- data/lib/nanoc3/extra/deployers.rb +12 -0
- data/lib/nanoc3/extra/file_proxy.rb +31 -0
- data/lib/nanoc3/extra/validators/links.rb +0 -0
- data/lib/nanoc3/extra/validators/w3c.rb +71 -0
- data/lib/nanoc3/extra/validators.rb +12 -0
- data/lib/nanoc3/extra/vcs.rb +65 -0
- data/lib/nanoc3/extra/vcses/bazaar.rb +21 -0
- data/lib/nanoc3/extra/vcses/dummy.rb +20 -0
- data/lib/nanoc3/extra/vcses/git.rb +21 -0
- data/lib/nanoc3/extra/vcses/mercurial.rb +21 -0
- data/lib/nanoc3/extra/vcses/subversion.rb +21 -0
- data/lib/nanoc3/extra/vcses.rb +17 -0
- data/lib/nanoc3/extra.rb +16 -0
- data/lib/nanoc3/filters/bluecloth.rb +13 -0
- data/lib/nanoc3/filters/coderay.rb +17 -0
- data/lib/nanoc3/filters/erb.rb +19 -0
- data/lib/nanoc3/filters/erubis.rb +17 -0
- data/lib/nanoc3/filters/haml.rb +20 -0
- data/lib/nanoc3/filters/less.rb +13 -0
- data/lib/nanoc3/filters/markaby.rb +14 -0
- data/lib/nanoc3/filters/maruku.rb +14 -0
- data/lib/nanoc3/filters/rainpress.rb +13 -0
- data/lib/nanoc3/filters/rdiscount.rb +13 -0
- data/lib/nanoc3/filters/rdoc.rb +23 -0
- data/lib/nanoc3/filters/redcloth.rb +14 -0
- data/lib/nanoc3/filters/relativize_paths.rb +32 -0
- data/lib/nanoc3/filters/rubypants.rb +14 -0
- data/lib/nanoc3/filters/sass.rb +17 -0
- data/lib/nanoc3/filters.rb +37 -0
- data/lib/nanoc3/helpers/blogging.rb +226 -0
- data/lib/nanoc3/helpers/breadcrumbs.rb +25 -0
- data/lib/nanoc3/helpers/capturing.rb +71 -0
- data/lib/nanoc3/helpers/filtering.rb +46 -0
- data/lib/nanoc3/helpers/html_escape.rb +22 -0
- data/lib/nanoc3/helpers/link_to.rb +120 -0
- data/lib/nanoc3/helpers/rendering.rb +76 -0
- data/lib/nanoc3/helpers/tagging.rb +58 -0
- data/lib/nanoc3/helpers/text.rb +40 -0
- data/lib/nanoc3/helpers/xml_sitemap.rb +69 -0
- data/lib/nanoc3/helpers.rb +16 -0
- data/lib/nanoc3/package.rb +106 -0
- data/lib/nanoc3/tasks/clean.rake +16 -0
- data/lib/nanoc3/tasks/clean.rb +33 -0
- data/lib/nanoc3/tasks/deploy/rsync.rake +11 -0
- data/lib/nanoc3/tasks/validate.rake +35 -0
- data/lib/nanoc3/tasks.rb +9 -0
- data/lib/nanoc3.rb +19 -0
- data/vendor/cri/ChangeLog +0 -0
- data/vendor/cri/LICENSE +19 -0
- data/vendor/cri/NEWS +0 -0
- data/vendor/cri/README +4 -0
- data/vendor/cri/Rakefile +25 -0
- data/vendor/cri/lib/cri/base.rb +153 -0
- data/vendor/cri/lib/cri/command.rb +105 -0
- data/vendor/cri/lib/cri/core_ext/string.rb +41 -0
- data/vendor/cri/lib/cri/core_ext.rb +8 -0
- data/vendor/cri/lib/cri/option_parser.rb +186 -0
- data/vendor/cri/lib/cri.rb +12 -0
- data/vendor/cri/test/test_base.rb +6 -0
- data/vendor/cri/test/test_command.rb +6 -0
- data/vendor/cri/test/test_core_ext.rb +21 -0
- data/vendor/cri/test/test_option_parser.rb +279 -0
- 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
|
data/lib/nanoc3/base.rb
ADDED
@@ -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
|