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.
- data/.gemtest +0 -0
- data/ChangeLog +3 -0
- data/Gemfile +32 -0
- data/LICENSE +19 -0
- data/NEWS.md +470 -0
- data/README.md +114 -0
- data/Rakefile +14 -0
- data/bin/nanoc +7 -27
- data/bin/nanoc3 +3 -0
- data/doc/yardoc_templates/default/layout/html/footer.erb +10 -0
- data/lib/nanoc.rb +41 -0
- data/lib/nanoc/base.rb +49 -0
- data/lib/nanoc/base/compilation/checksum_store.rb +57 -0
- data/lib/nanoc/base/compilation/compiled_content_cache.rb +62 -0
- data/lib/nanoc/base/compilation/compiler.rb +458 -0
- data/lib/nanoc/base/compilation/compiler_dsl.rb +214 -0
- data/lib/nanoc/base/compilation/dependency_tracker.rb +200 -0
- data/lib/nanoc/base/compilation/filter.rb +165 -0
- data/lib/nanoc/base/compilation/item_rep_proxy.rb +103 -0
- data/lib/nanoc/base/compilation/item_rep_recorder_proxy.rb +102 -0
- data/lib/nanoc/base/compilation/outdatedness_checker.rb +223 -0
- data/lib/nanoc/base/compilation/outdatedness_reasons.rb +46 -0
- data/lib/nanoc/base/compilation/rule.rb +73 -0
- data/lib/nanoc/base/compilation/rule_context.rb +84 -0
- data/lib/nanoc/base/compilation/rule_memory_calculator.rb +40 -0
- data/lib/nanoc/base/compilation/rule_memory_store.rb +53 -0
- data/lib/nanoc/base/compilation/rules_collection.rb +243 -0
- data/lib/nanoc/base/context.rb +47 -0
- data/lib/nanoc/base/core_ext.rb +6 -0
- data/lib/nanoc/base/core_ext/array.rb +62 -0
- data/lib/nanoc/base/core_ext/hash.rb +63 -0
- data/lib/nanoc/base/core_ext/pathname.rb +26 -0
- data/lib/nanoc/base/core_ext/string.rb +46 -0
- data/lib/nanoc/base/directed_graph.rb +275 -0
- data/lib/nanoc/base/errors.rb +211 -0
- data/lib/nanoc/base/memoization.rb +67 -0
- data/lib/nanoc/base/notification_center.rb +84 -0
- data/lib/nanoc/base/ordered_hash.rb +200 -0
- data/lib/nanoc/base/plugin_registry.rb +181 -0
- data/lib/nanoc/base/result_data/item_rep.rb +492 -0
- data/lib/nanoc/base/source_data/code_snippet.rb +58 -0
- data/lib/nanoc/base/source_data/configuration.rb +24 -0
- data/lib/nanoc/base/source_data/data_source.rb +234 -0
- data/lib/nanoc/base/source_data/item.rb +301 -0
- data/lib/nanoc/base/source_data/layout.rb +130 -0
- data/lib/nanoc/base/source_data/site.rb +361 -0
- data/lib/nanoc/base/store.rb +135 -0
- data/lib/nanoc/cli.rb +137 -0
- data/lib/nanoc/cli/command_runner.rb +104 -0
- data/lib/nanoc/cli/commands/autocompile.rb +58 -0
- data/lib/nanoc/cli/commands/compile.rb +297 -0
- data/lib/nanoc/cli/commands/create_item.rb +60 -0
- data/lib/nanoc/cli/commands/create_layout.rb +73 -0
- data/lib/nanoc/cli/commands/create_site.rb +411 -0
- data/lib/nanoc/cli/commands/debug.rb +117 -0
- data/lib/nanoc/cli/commands/deploy.rb +79 -0
- data/lib/nanoc/cli/commands/info.rb +98 -0
- data/lib/nanoc/cli/commands/nanoc.rb +38 -0
- data/lib/nanoc/cli/commands/prune.rb +50 -0
- data/lib/nanoc/cli/commands/update.rb +70 -0
- data/lib/nanoc/cli/commands/view.rb +82 -0
- data/lib/nanoc/cli/commands/watch.rb +124 -0
- data/lib/nanoc/cli/error_handler.rb +199 -0
- data/lib/nanoc/cli/logger.rb +92 -0
- data/lib/nanoc/data_sources.rb +29 -0
- data/lib/nanoc/data_sources/deprecated/delicious.rb +42 -0
- data/lib/nanoc/data_sources/deprecated/last_fm.rb +87 -0
- data/lib/nanoc/data_sources/deprecated/twitter.rb +38 -0
- data/lib/nanoc/data_sources/filesystem.rb +299 -0
- data/lib/nanoc/data_sources/filesystem_unified.rb +121 -0
- data/lib/nanoc/data_sources/filesystem_verbose.rb +91 -0
- data/lib/nanoc/extra.rb +24 -0
- data/lib/nanoc/extra/auto_compiler.rb +103 -0
- data/lib/nanoc/extra/chick.rb +125 -0
- data/lib/nanoc/extra/core_ext.rb +6 -0
- data/lib/nanoc/extra/core_ext/enumerable.rb +33 -0
- data/lib/nanoc/extra/core_ext/pathname.rb +30 -0
- data/lib/nanoc/extra/core_ext/time.rb +19 -0
- data/lib/nanoc/extra/deployer.rb +47 -0
- data/lib/nanoc/extra/deployers.rb +15 -0
- data/lib/nanoc/extra/deployers/fog.rb +98 -0
- data/lib/nanoc/extra/deployers/rsync.rb +70 -0
- data/lib/nanoc/extra/file_proxy.rb +40 -0
- data/lib/nanoc/extra/pruner.rb +86 -0
- data/lib/nanoc/extra/validators.rb +12 -0
- data/lib/nanoc/extra/validators/links.rb +268 -0
- data/lib/nanoc/extra/validators/w3c.rb +95 -0
- data/lib/nanoc/extra/vcs.rb +66 -0
- data/lib/nanoc/extra/vcses.rb +17 -0
- data/lib/nanoc/extra/vcses/bazaar.rb +25 -0
- data/lib/nanoc/extra/vcses/dummy.rb +24 -0
- data/lib/nanoc/extra/vcses/git.rb +25 -0
- data/lib/nanoc/extra/vcses/mercurial.rb +25 -0
- data/lib/nanoc/extra/vcses/subversion.rb +25 -0
- data/lib/nanoc/filters.rb +59 -0
- data/lib/nanoc/filters/asciidoc.rb +38 -0
- data/lib/nanoc/filters/bluecloth.rb +19 -0
- data/lib/nanoc/filters/coderay.rb +21 -0
- data/lib/nanoc/filters/coffeescript.rb +20 -0
- data/lib/nanoc/filters/colorize_syntax.rb +298 -0
- data/lib/nanoc/filters/erb.rb +38 -0
- data/lib/nanoc/filters/erubis.rb +34 -0
- data/lib/nanoc/filters/haml.rb +27 -0
- data/lib/nanoc/filters/kramdown.rb +20 -0
- data/lib/nanoc/filters/less.rb +53 -0
- data/lib/nanoc/filters/markaby.rb +20 -0
- data/lib/nanoc/filters/maruku.rb +20 -0
- data/lib/nanoc/filters/mustache.rb +24 -0
- data/lib/nanoc/filters/rainpress.rb +19 -0
- data/lib/nanoc/filters/rdiscount.rb +22 -0
- data/lib/nanoc/filters/rdoc.rb +33 -0
- data/lib/nanoc/filters/redcarpet.rb +62 -0
- data/lib/nanoc/filters/redcloth.rb +47 -0
- data/lib/nanoc/filters/relativize_paths.rb +94 -0
- data/lib/nanoc/filters/rubypants.rb +20 -0
- data/lib/nanoc/filters/sass.rb +74 -0
- data/lib/nanoc/filters/slim.rb +25 -0
- data/lib/nanoc/filters/typogruby.rb +23 -0
- data/lib/nanoc/filters/uglify_js.rb +42 -0
- data/lib/nanoc/filters/xsl.rb +46 -0
- data/lib/nanoc/filters/yui_compressor.rb +23 -0
- data/lib/nanoc/helpers.rb +16 -0
- data/lib/nanoc/helpers/blogging.rb +319 -0
- data/lib/nanoc/helpers/breadcrumbs.rb +40 -0
- data/lib/nanoc/helpers/capturing.rb +138 -0
- data/lib/nanoc/helpers/filtering.rb +50 -0
- data/lib/nanoc/helpers/html_escape.rb +55 -0
- data/lib/nanoc/helpers/link_to.rb +151 -0
- data/lib/nanoc/helpers/rendering.rb +140 -0
- data/lib/nanoc/helpers/tagging.rb +71 -0
- data/lib/nanoc/helpers/text.rb +44 -0
- data/lib/nanoc/helpers/xml_sitemap.rb +76 -0
- data/lib/nanoc/tasks.rb +10 -0
- data/lib/nanoc/tasks/clean.rake +16 -0
- data/lib/nanoc/tasks/clean.rb +29 -0
- data/lib/nanoc/tasks/deploy/rsync.rake +16 -0
- data/lib/nanoc/tasks/validate.rake +92 -0
- data/nanoc.gemspec +49 -0
- data/tasks/doc.rake +16 -0
- data/tasks/test.rake +46 -0
- data/test/base/core_ext/array_spec.rb +73 -0
- data/test/base/core_ext/hash_spec.rb +98 -0
- data/test/base/core_ext/pathname_spec.rb +27 -0
- data/test/base/core_ext/string_spec.rb +37 -0
- data/test/base/test_checksum_store.rb +35 -0
- data/test/base/test_code_snippet.rb +31 -0
- data/test/base/test_compiler.rb +403 -0
- data/test/base/test_compiler_dsl.rb +161 -0
- data/test/base/test_context.rb +31 -0
- data/test/base/test_data_source.rb +46 -0
- data/test/base/test_dependency_tracker.rb +262 -0
- data/test/base/test_directed_graph.rb +288 -0
- data/test/base/test_filter.rb +83 -0
- data/test/base/test_item.rb +179 -0
- data/test/base/test_item_rep.rb +579 -0
- data/test/base/test_layout.rb +59 -0
- data/test/base/test_memoization.rb +90 -0
- data/test/base/test_notification_center.rb +34 -0
- data/test/base/test_outdatedness_checker.rb +394 -0
- data/test/base/test_plugin.rb +30 -0
- data/test/base/test_rule.rb +19 -0
- data/test/base/test_rule_context.rb +65 -0
- data/test/base/test_site.rb +190 -0
- data/test/cli/commands/test_compile.rb +33 -0
- data/test/cli/commands/test_create_item.rb +14 -0
- data/test/cli/commands/test_create_layout.rb +28 -0
- data/test/cli/commands/test_create_site.rb +24 -0
- data/test/cli/commands/test_deploy.rb +74 -0
- data/test/cli/commands/test_help.rb +12 -0
- data/test/cli/commands/test_info.rb +11 -0
- data/test/cli/commands/test_prune.rb +98 -0
- data/test/cli/commands/test_update.rb +10 -0
- data/test/cli/test_cli.rb +102 -0
- data/test/cli/test_error_handler.rb +29 -0
- data/test/cli/test_logger.rb +10 -0
- data/test/data_sources/test_filesystem.rb +433 -0
- data/test/data_sources/test_filesystem_unified.rb +536 -0
- data/test/data_sources/test_filesystem_verbose.rb +357 -0
- data/test/extra/core_ext/test_enumerable.rb +30 -0
- data/test/extra/core_ext/test_pathname.rb +17 -0
- data/test/extra/core_ext/test_time.rb +15 -0
- data/test/extra/deployers/test_fog.rb +67 -0
- data/test/extra/deployers/test_rsync.rb +100 -0
- data/test/extra/test_auto_compiler.rb +417 -0
- data/test/extra/test_file_proxy.rb +19 -0
- data/test/extra/test_vcs.rb +22 -0
- data/test/extra/validators/test_links.rb +62 -0
- data/test/extra/validators/test_w3c.rb +47 -0
- data/test/filters/test_asciidoc.rb +22 -0
- data/test/filters/test_bluecloth.rb +18 -0
- data/test/filters/test_coderay.rb +44 -0
- data/test/filters/test_coffeescript.rb +18 -0
- data/test/filters/test_colorize_syntax.rb +379 -0
- data/test/filters/test_erb.rb +105 -0
- data/test/filters/test_erubis.rb +78 -0
- data/test/filters/test_haml.rb +96 -0
- data/test/filters/test_kramdown.rb +18 -0
- data/test/filters/test_less.rb +113 -0
- data/test/filters/test_markaby.rb +24 -0
- data/test/filters/test_maruku.rb +18 -0
- data/test/filters/test_mustache.rb +25 -0
- data/test/filters/test_rainpress.rb +29 -0
- data/test/filters/test_rdiscount.rb +31 -0
- data/test/filters/test_rdoc.rb +18 -0
- data/test/filters/test_redcarpet.rb +73 -0
- data/test/filters/test_redcloth.rb +33 -0
- data/test/filters/test_relativize_paths.rb +533 -0
- data/test/filters/test_rubypants.rb +18 -0
- data/test/filters/test_sass.rb +229 -0
- data/test/filters/test_slim.rb +35 -0
- data/test/filters/test_typogruby.rb +21 -0
- data/test/filters/test_uglify_js.rb +30 -0
- data/test/filters/test_xsl.rb +105 -0
- data/test/filters/test_yui_compressor.rb +44 -0
- data/test/gem_loader.rb +11 -0
- data/test/helper.rb +207 -0
- data/test/helpers/test_blogging.rb +754 -0
- data/test/helpers/test_breadcrumbs.rb +81 -0
- data/test/helpers/test_capturing.rb +41 -0
- data/test/helpers/test_filtering.rb +106 -0
- data/test/helpers/test_html_escape.rb +32 -0
- data/test/helpers/test_link_to.rb +249 -0
- data/test/helpers/test_rendering.rb +89 -0
- data/test/helpers/test_tagging.rb +87 -0
- data/test/helpers/test_text.rb +24 -0
- data/test/helpers/test_xml_sitemap.rb +103 -0
- data/test/tasks/test_clean.rb +67 -0
- metadata +327 -15
- data/bin/nanoc-select +0 -86
- 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
|
data/lib/nanoc/extra.rb
ADDED
|
@@ -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
|