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,121 @@
1
+ # encoding: utf-8
2
+
3
+ module Nanoc::DataSources
4
+
5
+ # The filesystem_unified data source stores its items and layouts in nested
6
+ # directories. Items and layouts are represented by one or two files; if it
7
+ # is represented using one file, the metadata can be contained in this file.
8
+ # The root directory for items is the `content` directory; for layouts, this
9
+ # is the `layouts` directory.
10
+ #
11
+ # The metadata for items and layouts can be stored in a separate file with
12
+ # the same base name but with the `.yaml` extension. If such a file is
13
+ # found, metadata is read from that file. Alternatively, the content file
14
+ # itself can start with a metadata section: it can be stored at the top of
15
+ # the file, between `---` (three dashes) separators. For example:
16
+ #
17
+ # ---
18
+ # title: "Moo!"
19
+ # ---
20
+ # h1. Hello!
21
+ #
22
+ # The metadata section can be omitted. If the file does not start with
23
+ # three or five dashes, the entire file will be considered as content.
24
+ #
25
+ # The identifier of items and layouts is determined as follows. A file with
26
+ # an `index.*` filename, such as `index.txt`, will have the filesystem path
27
+ # with the `index.*` part stripped as a identifier. For example:
28
+ #
29
+ # foo/bar/index.html → /foo/bar/
30
+ #
31
+ # In other cases, the identifier is calculated by stripping the extension.
32
+ # If the `allow_periods_in_identifiers` attribute in the configuration is
33
+ # true, only the last extension will be stripped if the file has multiple
34
+ # extensions; if it is false or unset, all extensions will be stripped.
35
+ # For example:
36
+ #
37
+ # (`allow_periods_in_identifiers` set to true)
38
+ # foo.entry.html → /foo.entry/
39
+ #
40
+ # (`allow_periods_in_identifiers` set to false)
41
+ # foo.html.erb → /foo/
42
+ #
43
+ # Note that each item must have an unique identifier. nanoc will display an
44
+ # error if two items with the same identifier are found.
45
+ #
46
+ # Some more examples:
47
+ #
48
+ # content/index.html → /
49
+ # content/foo.html → /foo/
50
+ # content/foo/index.html → /foo/
51
+ # content/foo/bar.html → /foo/bar/
52
+ # content/foo/bar.baz.html → /foo/bar/ OR /foo/bar.baz/
53
+ # content/foo/bar/index.html → /foo/bar/
54
+ # content/foo.bar/index.html → /foo.bar/
55
+ #
56
+ # The file extension does not determine the filters to run on items; the
57
+ # Rules file is used to specify processing instructors for each item.
58
+ #
59
+ # It is possible to set an explicit encoding that should be used when reading
60
+ # files. In the data source configuration, set `encoding` to an encoding
61
+ # understood by Ruby’s `Encoding`. If no encoding is set in the configuration,
62
+ # one will be inferred from the environment.
63
+ class FilesystemUnified < Nanoc::DataSource
64
+
65
+ include Nanoc::DataSources::Filesystem
66
+
67
+ private
68
+
69
+ # See {Nanoc::DataSources::Filesystem#create_object}.
70
+ def create_object(dir_name, content, attributes, identifier, params={})
71
+ # Check for periods
72
+ if (@config.nil? || !@config[:allow_periods_in_identifiers]) && identifier.include?('.')
73
+ raise RuntimeError,
74
+ "Attempted to create an object in #{dir_name} with identifier #{identifier} containing a period, but allow_periods_in_identifiers is not enabled in the site configuration. (Enabling allow_periods_in_identifiers may cause the site to break, though.)"
75
+ end
76
+
77
+ # Determine path
78
+ ext = params[:extension] || '.html'
79
+ path = dir_name + (identifier == '/' ? '/index.html' : identifier[0..-2] + ext)
80
+ parent_path = File.dirname(path)
81
+
82
+ # Notify
83
+ Nanoc::NotificationCenter.post(:file_created, path)
84
+
85
+ # Write item
86
+ FileUtils.mkdir_p(parent_path)
87
+ File.open(path, 'w') do |io|
88
+ meta = attributes.stringify_keys
89
+ unless meta == {}
90
+ io.write(YAML.dump(meta).strip + "\n")
91
+ io.write("---\n\n")
92
+ end
93
+ io.write(content)
94
+ end
95
+ end
96
+
97
+ # See {Nanoc::DataSources::Filesystem#filename_for}.
98
+ def filename_for(base_filename, ext)
99
+ if ext.nil?
100
+ nil
101
+ elsif ext.empty?
102
+ base_filename
103
+ else
104
+ base_filename + '.' + ext
105
+ end
106
+ end
107
+
108
+ # Returns the identifier derived from the given filename, first stripping
109
+ # the given directory name off the filename.
110
+ def identifier_for_filename(filename)
111
+ if filename =~ /(^|\/)index\.[^\/]+$/
112
+ regex = ((@config && @config[:allow_periods_in_identifiers]) ? /\/?index\.[^\/\.]+$/ : /\/?index\.[^\/]+$/)
113
+ else
114
+ regex = ((@config && @config[:allow_periods_in_identifiers]) ? /\.[^\/\.]+$/ : /\.[^\/]+$/)
115
+ end
116
+ filename.sub(regex, '').cleaned_identifier
117
+ end
118
+
119
+ end
120
+
121
+ end
@@ -0,0 +1,91 @@
1
+ # encoding: utf-8
2
+
3
+ module Nanoc::DataSources
4
+
5
+ # The filesystem_verbose data source is the old data source for a new nanoc
6
+ # site. It stores all data as files on the hard disk.
7
+ #
8
+ # None of the methods are documented in this file. See {Nanoc::DataSource}
9
+ # for documentation on the overridden methods instead.
10
+ #
11
+ # The filesystem_verbose data source stores its items and layouts in nested
12
+ # directories. Each directory represents a single item or layout. The root
13
+ # directory for items is the `content` directory; for layouts it is the
14
+ # `layouts` directory.
15
+ #
16
+ # Every directory has a content file and a meta file. The content file
17
+ # contains the actual item content, while the meta file contains the item’s
18
+ # or the layout’s metadata, formatted as YAML.
19
+ #
20
+ # Both content files and meta files are named after its parent directory
21
+ # (i.e. item). For example, an item/layout named `foo` will have a directory
22
+ # named `foo`, with e.g. a `foo.markdown` content file and a `foo.yaml` meta
23
+ # file.
24
+ #
25
+ # Content file extensions are not used for determining the filter that
26
+ # should be run; the meta file defines the list of filters. The meta file
27
+ # extension must always be `.yaml`, though.
28
+ #
29
+ # For backwards compatibility, content files can also have the `index`
30
+ # basename. Similarly, meta files can have the `meta` basename. For example,
31
+ # a parent directory named `foo` can have an `index.txt` content file and a
32
+ # `meta.yaml` meta file.
33
+ #
34
+ # The identifier is calculated by stripping the extension; if there is more
35
+ # than one extension, only the last extension is stripped and the previous
36
+ # extensions will be part of the identifier.
37
+ #
38
+ # It is possible to set an explicit encoding that should be used when reading
39
+ # files. In the data source configuration, set `encoding` to an encoding
40
+ # understood by Ruby’s `Encoding`. If no encoding is set in the configuration,
41
+ # one will be inferred from the environment.
42
+ class FilesystemVerbose < Nanoc::DataSource
43
+
44
+ include Nanoc::DataSources::Filesystem
45
+
46
+ private
47
+
48
+ # See {Nanoc::DataSources::Filesystem#create_object}.
49
+ def create_object(dir_name, content, attributes, identifier, params={})
50
+ # Determine base path
51
+ last_component = identifier.split('/')[-1] || dir_name
52
+ base_path = dir_name + identifier + last_component
53
+
54
+ # Get filenames
55
+ ext = params[:extension] || '.html'
56
+ dir_path = dir_name + identifier
57
+ meta_filename = dir_name + identifier + last_component + '.yaml'
58
+ content_filename = dir_name + identifier + last_component + ext
59
+
60
+ # Notify
61
+ Nanoc::NotificationCenter.post(:file_created, meta_filename)
62
+ Nanoc::NotificationCenter.post(:file_created, content_filename)
63
+
64
+ # Create files
65
+ FileUtils.mkdir_p(dir_path)
66
+ File.open(meta_filename, 'w') { |io| io.write(YAML.dump(attributes.stringify_keys)) }
67
+ File.open(content_filename, 'w') { |io| io.write(content) }
68
+ end
69
+
70
+ # See {Nanoc::DataSources::Filesystem#filename_for}.
71
+ def filename_for(base_filename, ext)
72
+ return nil if ext.nil?
73
+
74
+ last_component = base_filename[%r{[^/]+$}]
75
+ possibilities = [
76
+ base_filename + (ext.empty? ? '' : '.' + ext), # foo/bar.html
77
+ base_filename + '/' + last_component + (ext.empty? ? '' : '.' + ext), # foo/bar/bar.html
78
+ base_filename + '/' + 'index' + (ext.empty? ? '' : '.' + ext) # foo/bar/index.html
79
+ ]
80
+
81
+ possibilities.find { |p| File.file?(p) }
82
+ end
83
+
84
+ # See {Nanoc::DataSources::Filesystem#identifier_for_filename}.
85
+ def identifier_for_filename(filename)
86
+ filename.sub(/[^\/]+\.yaml$/, '')
87
+ end
88
+
89
+ end
90
+
91
+ end
@@ -0,0 +1,24 @@
1
+ # encoding: utf-8
2
+
3
+ module Nanoc::Extra
4
+
5
+ autoload 'AutoCompiler', 'nanoc/extra/auto_compiler'
6
+ autoload 'CHiCk', 'nanoc/extra/chick'
7
+ autoload 'Pruner', 'nanoc/extra/pruner'
8
+ autoload 'Validators', 'nanoc/extra/validators'
9
+
10
+ # Deprecated; use {Nanoc::Context} instead
11
+ # TODO [in nanoc 4.0] remove me
12
+ Context = ::Nanoc::Context
13
+
14
+ # Deprecated
15
+ # TODO [in nanoc 4.0] remove me
16
+ autoload 'FileProxy', 'nanoc/extra/file_proxy'
17
+
18
+ end
19
+
20
+ require 'nanoc/extra/core_ext'
21
+ require 'nanoc/extra/deployer'
22
+ require 'nanoc/extra/deployers'
23
+ require 'nanoc/extra/vcs'
24
+ require 'nanoc/extra/vcses'
@@ -0,0 +1,103 @@
1
+ # encoding: utf-8
2
+
3
+ module Nanoc::Extra
4
+
5
+ # A web server that will automatically compile items as they are requested.
6
+ # It also serves static files such as stylesheets and images.
7
+ class AutoCompiler
8
+
9
+ # @return [Nanoc::Site] The site this autocompiler belongs to
10
+ attr_reader :site
11
+
12
+ # Creates a new autocompiler for the given site.
13
+ #
14
+ # @param [String] site_path The path to the site to autocompile
15
+ def initialize(site_path)
16
+ require 'rack'
17
+ require 'mime/types'
18
+
19
+ # Set site
20
+ @site_path = site_path
21
+
22
+ # Create mutex to prevent parallel requests
23
+ require 'thread'
24
+ @mutex = Mutex.new
25
+ end
26
+
27
+ # Calls the autocompiler. The behaviour of this method is defined by the
28
+ # [Rack specification](http://rack.rubyforge.org/doc/files/SPEC.html).
29
+ #
30
+ # @param [Hash] env The environment, as defined by the Rack specification
31
+ #
32
+ # @return [Array] An array containing the status, the headers, and the
33
+ # body, as defined by the Rack specification
34
+ def call(env)
35
+ @mutex.synchronize do
36
+ # Start with a new site
37
+ build_site
38
+
39
+ # Find rep
40
+ path = Rack::Utils::unescape(env['PATH_INFO'])
41
+ reps = site.items.map { |i| i.reps }.flatten
42
+ rep = reps.find do |r|
43
+ r.path == path ||
44
+ r.raw_path == site.config[:output_dir] + path
45
+ end
46
+
47
+ # Recompile
48
+ site.compile if rep
49
+
50
+ # Get paths by appending index filenames
51
+ if path =~ /\/$/
52
+ possible_paths = site.config[:index_filenames].map { |f| path + f }
53
+ else
54
+ possible_paths = [ path ]
55
+ end
56
+
57
+ # Find matching file
58
+ modified_path = possible_paths.find { |f| File.file?(site.config[:output_dir] + f) }
59
+ modified_path ||= path
60
+
61
+ # Serve using Rack::File
62
+ puts "*** serving file #{modified_path}"
63
+ res = file_server.call(env.merge('PATH_INFO' => modified_path))
64
+ puts "*** done serving file #{modified_path}"
65
+ res
66
+ end
67
+ rescue StandardError, ScriptError => e
68
+ # Add compilation stack to env
69
+ env['nanoc.stack'] = []
70
+ stack.reverse.each do |obj|
71
+ if obj.is_a?(Nanoc::ItemRep) # item rep
72
+ env['nanoc.stack'] << "[item] #{obj.item.identifier} (rep #{obj.name})"
73
+ else # layout
74
+ env['nanoc.stack'] << "[layout] #{obj.identifier}"
75
+ end
76
+ end
77
+
78
+ # Re-raise error
79
+ raise e
80
+ end
81
+
82
+ private
83
+
84
+ def build_site
85
+ @site = Nanoc::Site.new(@site_path)
86
+ end
87
+
88
+ def mime_type_of(path, fallback)
89
+ mime_type = MIME::Types.of(path).first
90
+ mime_type = mime_type.nil? ? fallback : mime_type.simplified
91
+ end
92
+
93
+ def file_server
94
+ @file_server ||= ::Rack::File.new(site.config[:output_dir])
95
+ end
96
+
97
+ def stack
98
+ site.compiler.stack
99
+ end
100
+
101
+ end
102
+
103
+ end
@@ -0,0 +1,125 @@
1
+ require 'net/http'
2
+ require 'rack'
3
+ require 'rack/cache'
4
+
5
+ module Nanoc::Extra
6
+
7
+ # @deprecated Use a HTTP library such as
8
+ # [Net::HTTP](http://ruby-doc.org/stdlib/libdoc/net/http/rdoc/) or
9
+ # [Curb](http://curb.rubyforge.org/) instead.
10
+ module CHiCk
11
+
12
+ # @deprecated Use a HTTP library such as
13
+ # [Net::HTTP](http://ruby-doc.org/stdlib/libdoc/net/http/rdoc/) or
14
+ # [Curb](http://curb.rubyforge.org/) instead.
15
+ class Client
16
+
17
+ DEFAULT_OPTIONS = {
18
+ :cache => {
19
+ :metastore => 'file:tmp/rack/cache.meta',
20
+ :entitystore => 'file:tmp/rack/cache.body'
21
+ },
22
+ :cache_controller => {
23
+ :max_age => 60
24
+ }
25
+ }
26
+
27
+ def initialize(options={})
28
+ # Get options
29
+ @options = DEFAULT_OPTIONS.merge(options)
30
+ @options[:cache] = DEFAULT_OPTIONS[:cache].merge(@options[:cache])
31
+ @options[:cache_controller] = DEFAULT_OPTIONS[:cache_controller].merge(@options[:cache_controller])
32
+ end
33
+
34
+ def get(url)
35
+ # Build app
36
+ options = @options
37
+ @app ||= Rack::Builder.new {
38
+ use Rack::Cache, options[:cache].merge(:verbose => true)
39
+ use Nanoc::Extra::CHiCk::CacheController, options[:cache_controller]
40
+ run Nanoc::Extra::CHiCk::RackClient
41
+ }
42
+
43
+ # Build environment for request
44
+ env = Rack::MockRequest.env_for(url, :method => 'GET')
45
+
46
+ # Fetch
47
+ puts "[CHiCk] Fetching #{url}..." if $DEBUG
48
+ status, headers, body_parts = @app.call(env)
49
+ puts "[CHiCk] #{url}: #{headers['X-Rack-Cache']}" if $DEBUG
50
+
51
+ # Join body
52
+ body = ''
53
+ body_parts.each { |part| body << part }
54
+
55
+ # Done
56
+ [ status, headers, body ]
57
+ end
58
+
59
+ end
60
+
61
+ # @deprecated Use a HTTP library such as
62
+ # [Net::HTTP](http://ruby-doc.org/stdlib/libdoc/net/http/rdoc/) or
63
+ # [Curb](http://curb.rubyforge.org/) instead.
64
+ class CacheController
65
+
66
+ def initialize(app, options={})
67
+ @app = app
68
+ @options = options
69
+ end
70
+
71
+ def call(env)
72
+ res = @app.call(env)
73
+ unless res[1].has_key?('Cache-Control') || res[1].has_key?('Expires')
74
+ res[1]['Cache-Control'] = "max-age=#{@options[:max_age]}"
75
+ end
76
+ res
77
+ end
78
+
79
+ end
80
+
81
+ # @deprecated Use a HTTP library such as
82
+ # [Net::HTTP](http://ruby-doc.org/stdlib/libdoc/net/http/rdoc/) or
83
+ # [Curb](http://curb.rubyforge.org/) instead.
84
+ class RackClient
85
+
86
+ METHOD_TO_CLASS_MAPPING = {
87
+ 'DELETE' => Net::HTTP::Delete,
88
+ 'GET' => Net::HTTP::Get,
89
+ 'HEAD' => Net::HTTP::Head,
90
+ 'POST' => Net::HTTP::Post,
91
+ 'PUT' => Net::HTTP::Put
92
+ }
93
+
94
+ def self.call(env)
95
+ # Build request
96
+ request = Rack::Request.new(env)
97
+
98
+ # Build headers and strip HTTP_
99
+ request_headers = env.inject({}) do |m,(k,v)|
100
+ k =~ /^HTTP_(.*)$/ && v ? m.merge($1.gsub(/_/, '-') => v) : m
101
+ end
102
+
103
+ # Build Net::HTTP request
104
+ http = Net::HTTP.new(request.host, request.port)
105
+ net_http_request_class = METHOD_TO_CLASS_MAPPING[request.request_method]
106
+ raise ArgumentError, "Unsupported method: #{request.request_method}" if net_http_request_class.nil?
107
+ net_http_request = net_http_request_class.new(request.fullpath, request_headers)
108
+ net_http_request.body = env['rack.input'].read if [ 'POST', 'PUT' ].include?(request.request_method)
109
+
110
+ # Perform request
111
+ http.request(net_http_request) do |response|
112
+ # Build Rack response triplet
113
+ return [
114
+ response.code.to_i,
115
+ response.to_hash.inject({}) { |m,(k,v)| m.merge(k => v[0]) },
116
+ [ response.body ]
117
+ ]
118
+ end
119
+ end
120
+
121
+ end
122
+
123
+ end
124
+
125
+ end