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.
- 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
|