nanoc 3.2.4 → 3.3.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 (230) hide show
  1. data/.gemtest +0 -0
  2. data/ChangeLog +3 -0
  3. data/Gemfile +32 -0
  4. data/LICENSE +19 -0
  5. data/NEWS.md +470 -0
  6. data/README.md +114 -0
  7. data/Rakefile +14 -0
  8. data/bin/nanoc +7 -27
  9. data/bin/nanoc3 +3 -0
  10. data/doc/yardoc_templates/default/layout/html/footer.erb +10 -0
  11. data/lib/nanoc.rb +41 -0
  12. data/lib/nanoc/base.rb +49 -0
  13. data/lib/nanoc/base/compilation/checksum_store.rb +57 -0
  14. data/lib/nanoc/base/compilation/compiled_content_cache.rb +62 -0
  15. data/lib/nanoc/base/compilation/compiler.rb +458 -0
  16. data/lib/nanoc/base/compilation/compiler_dsl.rb +214 -0
  17. data/lib/nanoc/base/compilation/dependency_tracker.rb +200 -0
  18. data/lib/nanoc/base/compilation/filter.rb +165 -0
  19. data/lib/nanoc/base/compilation/item_rep_proxy.rb +103 -0
  20. data/lib/nanoc/base/compilation/item_rep_recorder_proxy.rb +102 -0
  21. data/lib/nanoc/base/compilation/outdatedness_checker.rb +223 -0
  22. data/lib/nanoc/base/compilation/outdatedness_reasons.rb +46 -0
  23. data/lib/nanoc/base/compilation/rule.rb +73 -0
  24. data/lib/nanoc/base/compilation/rule_context.rb +84 -0
  25. data/lib/nanoc/base/compilation/rule_memory_calculator.rb +40 -0
  26. data/lib/nanoc/base/compilation/rule_memory_store.rb +53 -0
  27. data/lib/nanoc/base/compilation/rules_collection.rb +243 -0
  28. data/lib/nanoc/base/context.rb +47 -0
  29. data/lib/nanoc/base/core_ext.rb +6 -0
  30. data/lib/nanoc/base/core_ext/array.rb +62 -0
  31. data/lib/nanoc/base/core_ext/hash.rb +63 -0
  32. data/lib/nanoc/base/core_ext/pathname.rb +26 -0
  33. data/lib/nanoc/base/core_ext/string.rb +46 -0
  34. data/lib/nanoc/base/directed_graph.rb +275 -0
  35. data/lib/nanoc/base/errors.rb +211 -0
  36. data/lib/nanoc/base/memoization.rb +67 -0
  37. data/lib/nanoc/base/notification_center.rb +84 -0
  38. data/lib/nanoc/base/ordered_hash.rb +200 -0
  39. data/lib/nanoc/base/plugin_registry.rb +181 -0
  40. data/lib/nanoc/base/result_data/item_rep.rb +492 -0
  41. data/lib/nanoc/base/source_data/code_snippet.rb +58 -0
  42. data/lib/nanoc/base/source_data/configuration.rb +24 -0
  43. data/lib/nanoc/base/source_data/data_source.rb +234 -0
  44. data/lib/nanoc/base/source_data/item.rb +301 -0
  45. data/lib/nanoc/base/source_data/layout.rb +130 -0
  46. data/lib/nanoc/base/source_data/site.rb +361 -0
  47. data/lib/nanoc/base/store.rb +135 -0
  48. data/lib/nanoc/cli.rb +137 -0
  49. data/lib/nanoc/cli/command_runner.rb +104 -0
  50. data/lib/nanoc/cli/commands/autocompile.rb +58 -0
  51. data/lib/nanoc/cli/commands/compile.rb +297 -0
  52. data/lib/nanoc/cli/commands/create_item.rb +60 -0
  53. data/lib/nanoc/cli/commands/create_layout.rb +73 -0
  54. data/lib/nanoc/cli/commands/create_site.rb +411 -0
  55. data/lib/nanoc/cli/commands/debug.rb +117 -0
  56. data/lib/nanoc/cli/commands/deploy.rb +79 -0
  57. data/lib/nanoc/cli/commands/info.rb +98 -0
  58. data/lib/nanoc/cli/commands/nanoc.rb +38 -0
  59. data/lib/nanoc/cli/commands/prune.rb +50 -0
  60. data/lib/nanoc/cli/commands/update.rb +70 -0
  61. data/lib/nanoc/cli/commands/view.rb +82 -0
  62. data/lib/nanoc/cli/commands/watch.rb +124 -0
  63. data/lib/nanoc/cli/error_handler.rb +199 -0
  64. data/lib/nanoc/cli/logger.rb +92 -0
  65. data/lib/nanoc/data_sources.rb +29 -0
  66. data/lib/nanoc/data_sources/deprecated/delicious.rb +42 -0
  67. data/lib/nanoc/data_sources/deprecated/last_fm.rb +87 -0
  68. data/lib/nanoc/data_sources/deprecated/twitter.rb +38 -0
  69. data/lib/nanoc/data_sources/filesystem.rb +299 -0
  70. data/lib/nanoc/data_sources/filesystem_unified.rb +121 -0
  71. data/lib/nanoc/data_sources/filesystem_verbose.rb +91 -0
  72. data/lib/nanoc/extra.rb +24 -0
  73. data/lib/nanoc/extra/auto_compiler.rb +103 -0
  74. data/lib/nanoc/extra/chick.rb +125 -0
  75. data/lib/nanoc/extra/core_ext.rb +6 -0
  76. data/lib/nanoc/extra/core_ext/enumerable.rb +33 -0
  77. data/lib/nanoc/extra/core_ext/pathname.rb +30 -0
  78. data/lib/nanoc/extra/core_ext/time.rb +19 -0
  79. data/lib/nanoc/extra/deployer.rb +47 -0
  80. data/lib/nanoc/extra/deployers.rb +15 -0
  81. data/lib/nanoc/extra/deployers/fog.rb +98 -0
  82. data/lib/nanoc/extra/deployers/rsync.rb +70 -0
  83. data/lib/nanoc/extra/file_proxy.rb +40 -0
  84. data/lib/nanoc/extra/pruner.rb +86 -0
  85. data/lib/nanoc/extra/validators.rb +12 -0
  86. data/lib/nanoc/extra/validators/links.rb +268 -0
  87. data/lib/nanoc/extra/validators/w3c.rb +95 -0
  88. data/lib/nanoc/extra/vcs.rb +66 -0
  89. data/lib/nanoc/extra/vcses.rb +17 -0
  90. data/lib/nanoc/extra/vcses/bazaar.rb +25 -0
  91. data/lib/nanoc/extra/vcses/dummy.rb +24 -0
  92. data/lib/nanoc/extra/vcses/git.rb +25 -0
  93. data/lib/nanoc/extra/vcses/mercurial.rb +25 -0
  94. data/lib/nanoc/extra/vcses/subversion.rb +25 -0
  95. data/lib/nanoc/filters.rb +59 -0
  96. data/lib/nanoc/filters/asciidoc.rb +38 -0
  97. data/lib/nanoc/filters/bluecloth.rb +19 -0
  98. data/lib/nanoc/filters/coderay.rb +21 -0
  99. data/lib/nanoc/filters/coffeescript.rb +20 -0
  100. data/lib/nanoc/filters/colorize_syntax.rb +298 -0
  101. data/lib/nanoc/filters/erb.rb +38 -0
  102. data/lib/nanoc/filters/erubis.rb +34 -0
  103. data/lib/nanoc/filters/haml.rb +27 -0
  104. data/lib/nanoc/filters/kramdown.rb +20 -0
  105. data/lib/nanoc/filters/less.rb +53 -0
  106. data/lib/nanoc/filters/markaby.rb +20 -0
  107. data/lib/nanoc/filters/maruku.rb +20 -0
  108. data/lib/nanoc/filters/mustache.rb +24 -0
  109. data/lib/nanoc/filters/rainpress.rb +19 -0
  110. data/lib/nanoc/filters/rdiscount.rb +22 -0
  111. data/lib/nanoc/filters/rdoc.rb +33 -0
  112. data/lib/nanoc/filters/redcarpet.rb +62 -0
  113. data/lib/nanoc/filters/redcloth.rb +47 -0
  114. data/lib/nanoc/filters/relativize_paths.rb +94 -0
  115. data/lib/nanoc/filters/rubypants.rb +20 -0
  116. data/lib/nanoc/filters/sass.rb +74 -0
  117. data/lib/nanoc/filters/slim.rb +25 -0
  118. data/lib/nanoc/filters/typogruby.rb +23 -0
  119. data/lib/nanoc/filters/uglify_js.rb +42 -0
  120. data/lib/nanoc/filters/xsl.rb +46 -0
  121. data/lib/nanoc/filters/yui_compressor.rb +23 -0
  122. data/lib/nanoc/helpers.rb +16 -0
  123. data/lib/nanoc/helpers/blogging.rb +319 -0
  124. data/lib/nanoc/helpers/breadcrumbs.rb +40 -0
  125. data/lib/nanoc/helpers/capturing.rb +138 -0
  126. data/lib/nanoc/helpers/filtering.rb +50 -0
  127. data/lib/nanoc/helpers/html_escape.rb +55 -0
  128. data/lib/nanoc/helpers/link_to.rb +151 -0
  129. data/lib/nanoc/helpers/rendering.rb +140 -0
  130. data/lib/nanoc/helpers/tagging.rb +71 -0
  131. data/lib/nanoc/helpers/text.rb +44 -0
  132. data/lib/nanoc/helpers/xml_sitemap.rb +76 -0
  133. data/lib/nanoc/tasks.rb +10 -0
  134. data/lib/nanoc/tasks/clean.rake +16 -0
  135. data/lib/nanoc/tasks/clean.rb +29 -0
  136. data/lib/nanoc/tasks/deploy/rsync.rake +16 -0
  137. data/lib/nanoc/tasks/validate.rake +92 -0
  138. data/nanoc.gemspec +49 -0
  139. data/tasks/doc.rake +16 -0
  140. data/tasks/test.rake +46 -0
  141. data/test/base/core_ext/array_spec.rb +73 -0
  142. data/test/base/core_ext/hash_spec.rb +98 -0
  143. data/test/base/core_ext/pathname_spec.rb +27 -0
  144. data/test/base/core_ext/string_spec.rb +37 -0
  145. data/test/base/test_checksum_store.rb +35 -0
  146. data/test/base/test_code_snippet.rb +31 -0
  147. data/test/base/test_compiler.rb +403 -0
  148. data/test/base/test_compiler_dsl.rb +161 -0
  149. data/test/base/test_context.rb +31 -0
  150. data/test/base/test_data_source.rb +46 -0
  151. data/test/base/test_dependency_tracker.rb +262 -0
  152. data/test/base/test_directed_graph.rb +288 -0
  153. data/test/base/test_filter.rb +83 -0
  154. data/test/base/test_item.rb +179 -0
  155. data/test/base/test_item_rep.rb +579 -0
  156. data/test/base/test_layout.rb +59 -0
  157. data/test/base/test_memoization.rb +90 -0
  158. data/test/base/test_notification_center.rb +34 -0
  159. data/test/base/test_outdatedness_checker.rb +394 -0
  160. data/test/base/test_plugin.rb +30 -0
  161. data/test/base/test_rule.rb +19 -0
  162. data/test/base/test_rule_context.rb +65 -0
  163. data/test/base/test_site.rb +190 -0
  164. data/test/cli/commands/test_compile.rb +33 -0
  165. data/test/cli/commands/test_create_item.rb +14 -0
  166. data/test/cli/commands/test_create_layout.rb +28 -0
  167. data/test/cli/commands/test_create_site.rb +24 -0
  168. data/test/cli/commands/test_deploy.rb +74 -0
  169. data/test/cli/commands/test_help.rb +12 -0
  170. data/test/cli/commands/test_info.rb +11 -0
  171. data/test/cli/commands/test_prune.rb +98 -0
  172. data/test/cli/commands/test_update.rb +10 -0
  173. data/test/cli/test_cli.rb +102 -0
  174. data/test/cli/test_error_handler.rb +29 -0
  175. data/test/cli/test_logger.rb +10 -0
  176. data/test/data_sources/test_filesystem.rb +433 -0
  177. data/test/data_sources/test_filesystem_unified.rb +536 -0
  178. data/test/data_sources/test_filesystem_verbose.rb +357 -0
  179. data/test/extra/core_ext/test_enumerable.rb +30 -0
  180. data/test/extra/core_ext/test_pathname.rb +17 -0
  181. data/test/extra/core_ext/test_time.rb +15 -0
  182. data/test/extra/deployers/test_fog.rb +67 -0
  183. data/test/extra/deployers/test_rsync.rb +100 -0
  184. data/test/extra/test_auto_compiler.rb +417 -0
  185. data/test/extra/test_file_proxy.rb +19 -0
  186. data/test/extra/test_vcs.rb +22 -0
  187. data/test/extra/validators/test_links.rb +62 -0
  188. data/test/extra/validators/test_w3c.rb +47 -0
  189. data/test/filters/test_asciidoc.rb +22 -0
  190. data/test/filters/test_bluecloth.rb +18 -0
  191. data/test/filters/test_coderay.rb +44 -0
  192. data/test/filters/test_coffeescript.rb +18 -0
  193. data/test/filters/test_colorize_syntax.rb +379 -0
  194. data/test/filters/test_erb.rb +105 -0
  195. data/test/filters/test_erubis.rb +78 -0
  196. data/test/filters/test_haml.rb +96 -0
  197. data/test/filters/test_kramdown.rb +18 -0
  198. data/test/filters/test_less.rb +113 -0
  199. data/test/filters/test_markaby.rb +24 -0
  200. data/test/filters/test_maruku.rb +18 -0
  201. data/test/filters/test_mustache.rb +25 -0
  202. data/test/filters/test_rainpress.rb +29 -0
  203. data/test/filters/test_rdiscount.rb +31 -0
  204. data/test/filters/test_rdoc.rb +18 -0
  205. data/test/filters/test_redcarpet.rb +73 -0
  206. data/test/filters/test_redcloth.rb +33 -0
  207. data/test/filters/test_relativize_paths.rb +533 -0
  208. data/test/filters/test_rubypants.rb +18 -0
  209. data/test/filters/test_sass.rb +229 -0
  210. data/test/filters/test_slim.rb +35 -0
  211. data/test/filters/test_typogruby.rb +21 -0
  212. data/test/filters/test_uglify_js.rb +30 -0
  213. data/test/filters/test_xsl.rb +105 -0
  214. data/test/filters/test_yui_compressor.rb +44 -0
  215. data/test/gem_loader.rb +11 -0
  216. data/test/helper.rb +207 -0
  217. data/test/helpers/test_blogging.rb +754 -0
  218. data/test/helpers/test_breadcrumbs.rb +81 -0
  219. data/test/helpers/test_capturing.rb +41 -0
  220. data/test/helpers/test_filtering.rb +106 -0
  221. data/test/helpers/test_html_escape.rb +32 -0
  222. data/test/helpers/test_link_to.rb +249 -0
  223. data/test/helpers/test_rendering.rb +89 -0
  224. data/test/helpers/test_tagging.rb +87 -0
  225. data/test/helpers/test_text.rb +24 -0
  226. data/test/helpers/test_xml_sitemap.rb +103 -0
  227. data/test/tasks/test_clean.rb +67 -0
  228. metadata +327 -15
  229. data/bin/nanoc-select +0 -86
  230. data/lib/nanoc-select.rb +0 -11
@@ -0,0 +1,130 @@
1
+ # encoding: utf-8
2
+
3
+ module Nanoc
4
+
5
+ # Represents a layout in a nanoc site. It has content, attributes, an
6
+ # identifier and a modification time (to speed up compilation).
7
+ class Layout
8
+
9
+ extend Nanoc::Memoization
10
+
11
+ # @return [String] The raw content of this layout
12
+ attr_reader :raw_content
13
+
14
+ # @return [Hash] This layout's attributes
15
+ attr_reader :attributes
16
+
17
+ # @return [String] This layout's identifier, starting and ending with a
18
+ # slash
19
+ attr_accessor :identifier
20
+
21
+ # Creates a new layout.
22
+ #
23
+ # @param [String] raw_content The raw content of this layout.
24
+ #
25
+ # @param [Hash] attributes A hash containing this layout's attributes.
26
+ #
27
+ # @param [String] identifier This layout's identifier.
28
+ #
29
+ # @param [Time, Hash] params Extra parameters. For backwards
30
+ # compatibility, this can be a Time instance indicating the time when
31
+ # this layout was last modified (mtime).
32
+ #
33
+ # @option params [Time, nil] :mtime (nil) The time when this layout was
34
+ # last modified. Deprecated; pass the modification time as the `:mtime`
35
+ # attribute instead.
36
+ def initialize(raw_content, attributes, identifier, params=nil)
37
+ @raw_content = raw_content
38
+ @attributes = attributes.symbolize_keys
39
+ @identifier = identifier.cleaned_identifier.freeze
40
+
41
+ # Set mtime
42
+ params ||= {}
43
+ params = { :mtime => params } if params.is_a?(Time)
44
+ @attributes.merge(:mtime => params[:mtime]) if params[:mtime]
45
+ end
46
+
47
+ # Requests the attribute with the given key.
48
+ #
49
+ # @param [Symbol] key The name of the attribute to fetch.
50
+ #
51
+ # @return [Object] The value of the requested attribute.
52
+ def [](key)
53
+ @attributes[key]
54
+ end
55
+
56
+ # Returns the type of this object. Will always return `:layout`, because
57
+ # this is a layout. For items, this method returns `:item`.
58
+ #
59
+ # @api private
60
+ #
61
+ # @return [Symbol] :layout
62
+ def type
63
+ :layout
64
+ end
65
+
66
+ # Prevents all further modifications to the layout.
67
+ #
68
+ # @return [void]
69
+ def freeze
70
+ attributes.freeze_recursively
71
+ identifier.freeze
72
+ raw_content.freeze
73
+ end
74
+
75
+ # Returns an object that can be used for uniquely identifying objects.
76
+ #
77
+ # @api private
78
+ #
79
+ # @return [Object] An unique reference to this object
80
+ def reference
81
+ [ type, self.identifier ]
82
+ end
83
+
84
+ def inspect
85
+ "<#{self.class} identifier=#{self.identifier}>"
86
+ end
87
+
88
+ # @return [String] The checksum for this object. If its contents change,
89
+ # the checksum will change as well.
90
+ def checksum
91
+ attributes = @attributes.dup
92
+ attributes.delete(:file)
93
+ @raw_content.checksum + ',' + attributes.checksum
94
+ end
95
+ memoize :checksum
96
+
97
+ def hash
98
+ self.class.hash ^ self.identifier.hash
99
+ end
100
+
101
+ def eql?(other)
102
+ self.class == other.class && self.identifier == other.identifier
103
+ end
104
+
105
+ def ==(other)
106
+ self.eql?(other)
107
+ end
108
+
109
+ def marshal_dump
110
+ [
111
+ @raw_content,
112
+ @attributes,
113
+ @identifier
114
+ ]
115
+ end
116
+
117
+ def marshal_load(source)
118
+ @raw_content,
119
+ @attributes,
120
+ @identifier = *source
121
+ end
122
+
123
+ # @deprecated Access the modification time using `layout[:mtime]` instead.
124
+ def mtime
125
+ self[:mtime]
126
+ end
127
+
128
+ end
129
+
130
+ end
@@ -0,0 +1,361 @@
1
+ # encoding: utf-8
2
+
3
+ module Nanoc
4
+
5
+ # The in-memory representation of a nanoc site. It holds references to the
6
+ # following site data:
7
+ #
8
+ # * {#items} — the list of items ({Nanoc::Item})
9
+ # * {#layouts} — the list of layouts ({Nanoc::Layout})
10
+ # * {#code_snippets} — the list of code snippets ({Nanoc::CodeSnippet})
11
+ # * {#data_sources} — the list of data sources ({Nanoc::DataSource})
12
+ #
13
+ # In addition, each site has a {#config} hash which stores the site
14
+ # configuration.
15
+ #
16
+ # The physical representation of a {Nanoc::Site} is usually a directory
17
+ # that contains a configuration file, site data, a rakefile, a rules file,
18
+ # etc. The way site data is stored depends on the data source.
19
+ class Site
20
+
21
+ # The default configuration for a data source. A data source's
22
+ # configuration overrides these options.
23
+ DEFAULT_DATA_SOURCE_CONFIG = {
24
+ :type => 'filesystem_unified',
25
+ :items_root => '/',
26
+ :layouts_root => '/',
27
+ :config => {}
28
+ }
29
+
30
+ # The default configuration for a site. A site's configuration overrides
31
+ # these options: when a {Nanoc::Site} is created with a configuration
32
+ # that lacks some options, the default value will be taken from
33
+ # `DEFAULT_CONFIG`.
34
+ DEFAULT_CONFIG = {
35
+ :text_extensions => %w( css erb haml htm html js less markdown md php rb sass scss txt xhtml xml coffee ),
36
+ :output_dir => 'output',
37
+ :data_sources => [ {} ],
38
+ :index_filenames => [ 'index.html' ],
39
+ :enable_output_diff => false
40
+ }
41
+
42
+ # Creates a site object for the site specified by the given
43
+ # `dir_or_config_hash` argument.
44
+ #
45
+ # @param [Hash, String] dir_or_config_hash If a string, contains the path
46
+ # to the site directory; if a hash, contains the site configuration.
47
+ def initialize(dir_or_config_hash)
48
+ build_config(dir_or_config_hash)
49
+ end
50
+
51
+ # Compiles the site.
52
+ #
53
+ # @return [void]
54
+ #
55
+ # @since 3.2.0
56
+ def compile
57
+ compiler.run
58
+ end
59
+
60
+ # Returns the compiler for this site. Will create a new compiler if none
61
+ # exists yet.
62
+ #
63
+ # @return [Nanoc::Compiler] The compiler for this site
64
+ def compiler
65
+ @compiler ||= Compiler.new(self)
66
+ end
67
+
68
+ # Returns the data sources for this site. Will create a new data source if
69
+ # none exists yet.
70
+ #
71
+ # @return [Array<Nanoc::DataSource>] The list of data sources for this
72
+ # site
73
+ #
74
+ # @raise [Nanoc::Errors::UnknownDataSource] if the site configuration
75
+ # specifies an unknown data source
76
+ def data_sources
77
+ load_code_snippets
78
+
79
+ @data_sources ||= begin
80
+ @config[:data_sources].map do |data_source_hash|
81
+ # Get data source class
82
+ data_source_class = Nanoc::DataSource.named(data_source_hash[:type])
83
+ raise Nanoc::Errors::UnknownDataSource.new(data_source_hash[:type]) if data_source_class.nil?
84
+
85
+ # Warn about deprecated data sources
86
+ # TODO [in nanoc 4.0] remove me
87
+ case data_source_hash[:type]
88
+ when 'filesystem'
89
+ warn "Warning: the 'filesystem' data source has been renamed to 'filesystem_verbose'. Using 'filesystem' will work in nanoc 3.1.x, but it will likely not work anymore in a future release of nanoc. Please update your data source configuration and replace 'filesystem' with 'filesystem_verbose'."
90
+ when 'filesystem_combined', 'filesystem_compact'
91
+ warn "Warning: the 'filesystem_combined' and 'filesystem_compact' data source has been merged into the new 'filesystem_unified' data source. Using 'filesystem_combined' and 'filesystem_compact' will work in nanoc 3.1.x, but it will likely not work anymore in a future release of nanoc. Please update your data source configuration and replace 'filesystem_combined' and 'filesystem_compact with 'filesystem_unified'."
92
+ end
93
+
94
+ # Create data source
95
+ data_source_class.new(
96
+ self,
97
+ data_source_hash[:items_root],
98
+ data_source_hash[:layouts_root],
99
+ data_source_hash.merge(data_source_hash[:config] || {})
100
+ )
101
+ end
102
+ end
103
+ end
104
+
105
+ # Returns this site’s code snippets.
106
+ #
107
+ # @return [Array<Nanoc::CodeSnippet>] The list of code snippets in this
108
+ # site
109
+ def code_snippets
110
+ load
111
+ @code_snippets
112
+ end
113
+
114
+ # Returns this site’s items.
115
+ #
116
+ # @return [Array<Nanoc::Item>] The list of items in this site
117
+ def items
118
+ load
119
+ @items
120
+ end
121
+
122
+ # Returns this site’s layouts.
123
+ #
124
+ # @return [Array<Nanoc::Layouts>] The list of layout in this site
125
+ def layouts
126
+ load
127
+ @layouts
128
+ end
129
+
130
+ # Returns the site configuration. It has the following keys:
131
+ #
132
+ # * `text_extensions` (`Array<String>`) - A list of file extensions that
133
+ # will cause nanoc to threat the file as textual instead of binary. When
134
+ # the data source finds a content file with an extension that is
135
+ # included in this list, it will be marked as textual.
136
+ #
137
+ # * `output_dir` (`String`) - The directory to which compiled items will
138
+ # be written. This path is relative to the current working directory,
139
+ # but can also be an absolute path.
140
+ #
141
+ # * `data_sources` (`Array<Hash>`) - A list of data sources for this site.
142
+ # See below for documentation on the structure of this list. By default,
143
+ # there is only one data source of the filesystem type mounted at `/`.
144
+ #
145
+ # * `index_filenames` (`Array<String>`) - A list of filenames that will be
146
+ # stripped off full item paths to create cleaner URLs. For example,
147
+ # `/about/` will be used instead of `/about/index.html`). The default
148
+ # value should be okay in most cases.
149
+ #
150
+ # * `enable_output_diff` (`Boolean`) - True when diffs should be generated
151
+ # for the compiled content of this site; false otherwise.
152
+ #
153
+ # The list of data sources consists of hashes with the following keys:
154
+ #
155
+ # * `:type` (`String`) - The type of data source, i.e. its identifier.
156
+ #
157
+ # * `:items_root` (`String`) - The prefix that should be given to all
158
+ # items returned by the {#items} method (comparable to mount points
159
+ # for filesystems in Unix-ish OSes).
160
+ #
161
+ # * `:layouts_root` (`String`) - The prefix that should be given to all
162
+ # layouts returned by the {#layouts} method (comparable to mount
163
+ # points for filesystems in Unix-ish OSes).
164
+ #
165
+ # * `:config` (`Hash`) - A hash containing the configuration for this data
166
+ # source. nanoc itself does not use this hash. This is especially
167
+ # useful for online data sources; for example, a Twitter data source
168
+ # would need the username of the account from which to fetch tweets.
169
+ #
170
+ # @return [Hash] The site configuration
171
+ def config
172
+ @config
173
+ end
174
+
175
+ # Fills each item's parent reference and children array with the
176
+ # appropriate items. It is probably not necessary to call this method
177
+ # manually; it will be called when appropriate.
178
+ #
179
+ # @return [void]
180
+ def setup_child_parent_links
181
+ teardown_child_parent_links
182
+
183
+ items = @items.sort_by { |i| i.identifier }
184
+ items.each_with_index do |item, index|
185
+ # Get parent
186
+ next if index == 0
187
+ parent_identifier = item.identifier.sub(/[^\/]+\/$/, '')
188
+ parent = nil
189
+ (index-1).downto(0) do |candidate_index|
190
+ candidate = items[candidate_index]
191
+ if candidate.identifier == parent_identifier
192
+ parent = candidate
193
+ elsif candidate.identifier[0..parent_identifier.size-1] != parent_identifier
194
+ break
195
+ end
196
+ end
197
+ next if parent.nil?
198
+
199
+ # Link
200
+ item.parent = parent
201
+ parent.children << item
202
+ end
203
+ end
204
+
205
+ # Removes all child-parent links.
206
+ #
207
+ # @api private
208
+ #
209
+ # @return [void]
210
+ def teardown_child_parent_links
211
+ @items.each do |item|
212
+ item.parent = nil
213
+ item.children = []
214
+ end
215
+ end
216
+
217
+ # Prevents all further modifications to itself, its items, its layouts etc.
218
+ #
219
+ # @return [void]
220
+ def freeze
221
+ config.freeze_recursively
222
+ items.each { |i| i.freeze }
223
+ layouts.each { |l| l.freeze }
224
+ code_snippets.each { |cs| cs.freeze }
225
+ end
226
+
227
+ # @deprecated It is no longer necessary to explicitly load site data. It
228
+ # is safe to remove all {#load_data} calls.
229
+ def load_data(force=false)
230
+ warn 'It is no longer necessary to call Nanoc::Site#load_data. This method no longer has any effect. All calls to this method can be safely removed.'
231
+ end
232
+
233
+ # Loads the site data. It is not necessary to call this method explicitly;
234
+ # it will be called when it is necessary.
235
+ #
236
+ # @api private
237
+ #
238
+ # @return [void]
239
+ def load
240
+ return if @loaded || @loading
241
+ @loading = true
242
+
243
+ # Load all data
244
+ load_code_snippets
245
+ data_sources.each { |ds| ds.use }
246
+ load_items
247
+ load_layouts
248
+ data_sources.each { |ds| ds.unuse }
249
+ setup_child_parent_links
250
+
251
+ # Load compiler too
252
+ # FIXME this should not be necessary
253
+ compiler.load
254
+
255
+ @loaded = true
256
+ rescue => e
257
+ unload
258
+ raise e
259
+ ensure
260
+ @loading = false
261
+ end
262
+
263
+ # Undoes the effects of {#load}. Used when {#load} raises an exception.
264
+ #
265
+ # @api private
266
+ def unload
267
+ return if @unloading
268
+ @unloading = true
269
+
270
+ @items_loaded = false
271
+ @items = []
272
+ @layouts_loaded = false
273
+ @layouts = []
274
+ @code_snippets_loaded = false
275
+ @code_snippets = []
276
+
277
+ compiler.unload
278
+
279
+ @loaded = false
280
+ @unloading = false
281
+ end
282
+
283
+ private
284
+
285
+ # Loads this site’s code and executes it.
286
+ def load_code_snippets
287
+ @code_snippets_loaded ||= false
288
+ return if @code_snippets_loaded
289
+ @code_snippets_loaded = true
290
+
291
+ # Get code snippets
292
+ @code_snippets = Dir['lib/**/*.rb'].sort.map do |filename|
293
+ Nanoc::CodeSnippet.new(
294
+ File.read(filename),
295
+ filename
296
+ )
297
+ end
298
+
299
+ # Execute code snippets
300
+ @code_snippets.each { |cs| cs.load }
301
+ end
302
+
303
+ # Loads this site’s items, sets up item child-parent relationships and
304
+ # builds each item's list of item representations.
305
+ def load_items
306
+ @items_loaded ||= false
307
+ return if @items_loaded
308
+ @items_loaded = true
309
+
310
+ # Get items
311
+ @items = []
312
+ data_sources.each do |ds|
313
+ items_in_ds = ds.items
314
+ items_in_ds.each { |i| i.identifier = File.join(ds.items_root, i.identifier) }
315
+ @items.concat(items_in_ds)
316
+ end
317
+ end
318
+
319
+ # Loads this site’s layouts.
320
+ def load_layouts
321
+ @layouts_loaded ||= false
322
+ return if @layouts_loaded
323
+ @layouts_loaded = true
324
+
325
+ # Get layouts
326
+ @layouts = []
327
+ data_sources.each do |ds|
328
+ layouts_in_ds = ds.layouts
329
+ layouts_in_ds.each { |i| i.identifier = File.join(ds.layouts_root, i.identifier) }
330
+ @layouts.concat(layouts_in_ds)
331
+ end
332
+ end
333
+
334
+ # Builds the configuration hash based on the given argument. Also see
335
+ # {#initialize} for details.
336
+ def build_config(dir_or_config_hash)
337
+ if dir_or_config_hash.is_a? String
338
+ # Check whether it is supported
339
+ if dir_or_config_hash != '.'
340
+ warn 'WARNING: Calling Nanoc::Site.new with a directory that is not the current working directory is not supported. It is recommended to change the directory before calling Nanoc::Site.new. For example, instead of Nanoc::Site.new(\'abc\'), use Dir.chdir(\'abc\') { Nanoc::Site.new(\'.\') }.'
341
+ end
342
+
343
+ # Read config from config.yaml in given dir
344
+ config_path = File.join(dir_or_config_hash, 'config.yaml')
345
+ @config = DEFAULT_CONFIG.merge(YAML.load_file(config_path).symbolize_keys)
346
+ @config[:data_sources].map! { |ds| ds.symbolize_keys }
347
+ else
348
+ # Use passed config hash
349
+ @config = DEFAULT_CONFIG.merge(dir_or_config_hash)
350
+ end
351
+
352
+ # Merge data sources with default data source config
353
+ @config[:data_sources] = @config[:data_sources].map { |ds| DEFAULT_DATA_SOURCE_CONFIG.merge(ds) }
354
+
355
+ # Convert to proper configuration
356
+ @config = Nanoc::Configuration.new(@config)
357
+ end
358
+
359
+ end
360
+
361
+ end