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,82 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
usage 'view [options]'
|
|
4
|
+
summary 'start the web server that serves static files'
|
|
5
|
+
description <<-EOS
|
|
6
|
+
Start the static web server. Unless specified, the web server will run on port 3000 and listen on all IP addresses. Running this static web server requires 'adsf' (not 'asdf'!).
|
|
7
|
+
EOS
|
|
8
|
+
|
|
9
|
+
required :H, :handler, 'specify the handler to use (webrick/mongrel/...)'
|
|
10
|
+
required :o, :host, 'specify the host to listen on (default: 0.0.0.0)'
|
|
11
|
+
required :p, :port, 'specify the port to listen on (default: 3000)'
|
|
12
|
+
|
|
13
|
+
module Nanoc::CLI::Commands
|
|
14
|
+
|
|
15
|
+
class View < ::Nanoc::CLI::CommandRunner
|
|
16
|
+
|
|
17
|
+
def run
|
|
18
|
+
load_adsf
|
|
19
|
+
require 'rack'
|
|
20
|
+
|
|
21
|
+
# Make sure we are in a nanoc site directory
|
|
22
|
+
self.require_site
|
|
23
|
+
|
|
24
|
+
# Set options
|
|
25
|
+
options_for_rack = {
|
|
26
|
+
:Port => (options[:port] || 3000).to_i,
|
|
27
|
+
:Host => (options[:host] || '0.0.0.0')
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
# Guess which handler we should use
|
|
31
|
+
unless handler = Rack::Handler.get(options[:handler])
|
|
32
|
+
begin
|
|
33
|
+
handler = Rack::Handler::Mongrel
|
|
34
|
+
rescue LoadError => e
|
|
35
|
+
handler = Rack::Handler::WEBrick
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Build app
|
|
40
|
+
site = self.site
|
|
41
|
+
app = Rack::Builder.new do
|
|
42
|
+
use Rack::CommonLogger
|
|
43
|
+
use Rack::ShowExceptions
|
|
44
|
+
use Rack::Lint
|
|
45
|
+
use Rack::Head
|
|
46
|
+
use Adsf::Rack::IndexFileFinder, :root => site.config[:output_dir]
|
|
47
|
+
run Rack::File.new(site.config[:output_dir])
|
|
48
|
+
end.to_app
|
|
49
|
+
|
|
50
|
+
# Run autocompiler
|
|
51
|
+
handler.run(app, options_for_rack)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
protected
|
|
55
|
+
|
|
56
|
+
def load_adsf
|
|
57
|
+
# Load adsf
|
|
58
|
+
begin
|
|
59
|
+
require 'adsf'
|
|
60
|
+
return
|
|
61
|
+
rescue LoadError
|
|
62
|
+
$stderr.puts "Could not find the required 'adsf' gem, " \
|
|
63
|
+
"which is necessary for the view command."
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Check asdf
|
|
67
|
+
begin
|
|
68
|
+
require 'asdf'
|
|
69
|
+
$stderr.puts "You appear to have 'asdf' installed, " \
|
|
70
|
+
"but not 'adsf'. Please install 'adsf' (check the spelling)!"
|
|
71
|
+
rescue LoadError
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Done
|
|
75
|
+
exit 1
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
runner Nanoc::CLI::Commands::View
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
usage 'watch [options]'
|
|
4
|
+
summary 'start the watcher'
|
|
5
|
+
description <<-EOS
|
|
6
|
+
Start the watcher. When a change is detected, the site will be recompiled.
|
|
7
|
+
EOS
|
|
8
|
+
|
|
9
|
+
module Nanoc::CLI::Commands
|
|
10
|
+
|
|
11
|
+
class Watch < ::Nanoc::CLI::CommandRunner
|
|
12
|
+
|
|
13
|
+
def run
|
|
14
|
+
require 'fssm'
|
|
15
|
+
require 'pathname'
|
|
16
|
+
|
|
17
|
+
require_site
|
|
18
|
+
watcher_config = self.site.config[:watcher] || {}
|
|
19
|
+
|
|
20
|
+
@notifier = Notifier.new
|
|
21
|
+
|
|
22
|
+
# Define rebuilder
|
|
23
|
+
rebuilder = lambda do |base, relative|
|
|
24
|
+
# Determine filename
|
|
25
|
+
if base.nil? || relative.nil?
|
|
26
|
+
filename = nil
|
|
27
|
+
else
|
|
28
|
+
filename = ::Pathname.new(File.join([ base, relative ])).relative_path_from(::Pathname.new(Dir.getwd)).to_s
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Notify
|
|
32
|
+
if filename
|
|
33
|
+
print "Change detected to #{filename}; recompiling… ".make_compatible_with_env
|
|
34
|
+
else
|
|
35
|
+
print "Watcher started; compiling the entire site… ".make_compatible_with_env
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Recompile
|
|
39
|
+
start = Time.now
|
|
40
|
+
site = Nanoc::Site.new('.')
|
|
41
|
+
begin
|
|
42
|
+
site.compile
|
|
43
|
+
|
|
44
|
+
# TODO include icon (--image misc/success-icon.png)
|
|
45
|
+
notify_on_compilation_success = watcher_config.fetch(:notify_on_compilation_success) { true }
|
|
46
|
+
if notify_on_compilation_success
|
|
47
|
+
@notifier.notify('Compilation complete')
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
time_spent = ((Time.now - start)*1000.0).round
|
|
51
|
+
puts "done in #{format '%is %ims', *(time_spent.divmod(1000))}"
|
|
52
|
+
rescue Exception => e
|
|
53
|
+
# TODO include icon (--image misc/error-icon.png)
|
|
54
|
+
notify_on_compilation_failure = watcher_config.fetch(:notify_on_compilation_failure) { true }
|
|
55
|
+
if notify_on_compilation_failure
|
|
56
|
+
@notifier.notify('Compilation failed')
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
puts
|
|
60
|
+
Nanoc::CLI::ErrorHandler.print_error(e)
|
|
61
|
+
puts
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Rebuild once
|
|
66
|
+
rebuilder.call(nil, nil)
|
|
67
|
+
|
|
68
|
+
# Get directories to watch
|
|
69
|
+
dirs_to_watch = watcher_config[:dirs_to_watch] || %w( content layouts lib )
|
|
70
|
+
files_to_watch = watcher_config[:files_to_watch] || %w( config.yaml Rules rules Rules.rb rules.rb' )
|
|
71
|
+
files_to_watch.delete_if { |f| !File.file?(f) }
|
|
72
|
+
|
|
73
|
+
# Watch
|
|
74
|
+
puts "Watching for changes…".make_compatible_with_env
|
|
75
|
+
watcher = lambda do |*args|
|
|
76
|
+
update(&rebuilder)
|
|
77
|
+
delete(&rebuilder)
|
|
78
|
+
create(&rebuilder)
|
|
79
|
+
end
|
|
80
|
+
monitor = FSSM::Monitor.new
|
|
81
|
+
dirs_to_watch.each { |dir| monitor.path(dir, '**/*', &watcher) }
|
|
82
|
+
files_to_watch.each { |filename| monitor.file(filename, &watcher) }
|
|
83
|
+
monitor.run
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Allows sending user notifications in a cross-platform way.
|
|
87
|
+
class Notifier
|
|
88
|
+
|
|
89
|
+
# A list of commandline tool names that can be used to send notifications
|
|
90
|
+
TOOLS = %w( growlnotify notify-send )
|
|
91
|
+
|
|
92
|
+
# The tool to use for discovering binaries' locations
|
|
93
|
+
FIND_BINARY_COMMAND = RUBY_PLATFORM =~ /mingw|mswin/ ? "where" : "which"
|
|
94
|
+
|
|
95
|
+
# Send a notification. If no notifier is found, no notification will be
|
|
96
|
+
# created.
|
|
97
|
+
#
|
|
98
|
+
# @param [String] message The message to include in the notification
|
|
99
|
+
def notify(message)
|
|
100
|
+
return if tool.nil?
|
|
101
|
+
send(tool.tr('-', '_'), message)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
private
|
|
105
|
+
|
|
106
|
+
def tool
|
|
107
|
+
@tool ||= TOOLS.find { |t| !`#{FIND_BINARY_COMMAND} #{t}`.empty? }
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def growlnotify(message)
|
|
111
|
+
system('growlnotify', '-m', message)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def notify_send(message)
|
|
115
|
+
system('notify-send', message)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
runner Nanoc::CLI::Commands::Watch
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module Nanoc::CLI
|
|
4
|
+
|
|
5
|
+
# Catches errors and prints nice diagnostic messages, then exits.
|
|
6
|
+
#
|
|
7
|
+
# @api private
|
|
8
|
+
class ErrorHandler
|
|
9
|
+
|
|
10
|
+
# @option params [Nanoc::CLI::Command, nil] command The command that is
|
|
11
|
+
# currently being executed, or nil if there is none
|
|
12
|
+
def initialize(params={})
|
|
13
|
+
@command = params[:command]
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Enables error handling in the given block.
|
|
17
|
+
#
|
|
18
|
+
# @option params [Nanoc::CLI::Command, nil] command The command that is
|
|
19
|
+
# currently being executed, or nil if there is none
|
|
20
|
+
#
|
|
21
|
+
# @return [void]
|
|
22
|
+
def self.handle_while(params={}, &block)
|
|
23
|
+
self.new(params).handle_while(&block)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Enables error handling in the given block. This method should not be
|
|
27
|
+
# called directly; use {Nanoc::CLI::ErrorHandler.handle_while} instead.
|
|
28
|
+
#
|
|
29
|
+
# @return [void]
|
|
30
|
+
#
|
|
31
|
+
# @api private
|
|
32
|
+
def handle_while(&block)
|
|
33
|
+
# Set exit handler
|
|
34
|
+
[ 'INT', 'TERM' ].each do |signal|
|
|
35
|
+
Signal.trap(signal) do
|
|
36
|
+
puts
|
|
37
|
+
exit!(0)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Run
|
|
42
|
+
yield
|
|
43
|
+
rescue Interrupt => e
|
|
44
|
+
exit(1)
|
|
45
|
+
rescue StandardError, ScriptError => e
|
|
46
|
+
self.print_error(e)
|
|
47
|
+
exit(1)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Prints the given error to stderr. Includes message, possible resolution
|
|
51
|
+
# (see {#resolution_for}), compilation stack, backtrace, etc.
|
|
52
|
+
#
|
|
53
|
+
# @param [Error] error The error that should be described
|
|
54
|
+
#
|
|
55
|
+
# @return [void]
|
|
56
|
+
def self.print_error(error)
|
|
57
|
+
self.new.print_error(error)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Prints the given error to stderr. Includes message, possible resolution
|
|
61
|
+
# (see {#resolution_for}), compilation stack, backtrace, etc.
|
|
62
|
+
#
|
|
63
|
+
# @param [Error] error The error that should be described
|
|
64
|
+
#
|
|
65
|
+
# @return [void]
|
|
66
|
+
def print_error(error)
|
|
67
|
+
# Header
|
|
68
|
+
$stderr.puts
|
|
69
|
+
$stderr.puts "Captain! We’ve been hit!"
|
|
70
|
+
|
|
71
|
+
# Exception and resolution (if any)
|
|
72
|
+
$stderr.puts
|
|
73
|
+
$stderr.puts '=== MESSAGE:'
|
|
74
|
+
$stderr.puts
|
|
75
|
+
$stderr.puts "#{error.class}: #{error.message}"
|
|
76
|
+
resolution = self.resolution_for(error)
|
|
77
|
+
$stderr.puts "#{resolution}" if resolution
|
|
78
|
+
|
|
79
|
+
# Compilation stack
|
|
80
|
+
$stderr.puts
|
|
81
|
+
$stderr.puts '=== COMPILATION STACK:'
|
|
82
|
+
$stderr.puts
|
|
83
|
+
if self.stack.empty?
|
|
84
|
+
$stderr.puts " (empty)"
|
|
85
|
+
else
|
|
86
|
+
self.stack.reverse.each do |obj|
|
|
87
|
+
if obj.is_a?(Nanoc::ItemRep)
|
|
88
|
+
$stderr.puts " - [item] #{obj.item.identifier} (rep #{obj.name})"
|
|
89
|
+
else # layout
|
|
90
|
+
$stderr.puts " - [layout] #{obj.identifier}"
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Backtrace
|
|
96
|
+
$stderr.puts
|
|
97
|
+
$stderr.puts '=== BACKTRACE:'
|
|
98
|
+
$stderr.puts
|
|
99
|
+
$stderr.puts error.backtrace.to_enum(:each_with_index).map { |item, index| " #{index}. #{item}" }.join("\n")
|
|
100
|
+
|
|
101
|
+
# Extra information
|
|
102
|
+
$stderr.puts
|
|
103
|
+
$stderr.puts '=== VERSION INFORMATION:'
|
|
104
|
+
$stderr.puts
|
|
105
|
+
$stderr.puts Nanoc.version_information
|
|
106
|
+
|
|
107
|
+
# Issue link
|
|
108
|
+
$stderr.puts
|
|
109
|
+
$stderr.puts "If you believe this is a bug in nanoc, please do report it at"
|
|
110
|
+
$stderr.puts "<https://github.com/ddfreyne/nanoc/issues/new>--thanks!"
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
protected
|
|
114
|
+
|
|
115
|
+
# @return [Boolean] true if debug output is enabled, false if not
|
|
116
|
+
#
|
|
117
|
+
# @see Nanoc::CLI.debug?
|
|
118
|
+
def debug?
|
|
119
|
+
Nanoc::CLI.debug?
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# @return [Nanoc::Site] The site that is currently being processed
|
|
123
|
+
def site
|
|
124
|
+
@command && @command.site
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# @return [Nanoc::Compiler] The compiler for the current site
|
|
128
|
+
def compiler
|
|
129
|
+
site && site.compiler
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# @return [Array] The current compilation stack
|
|
133
|
+
def stack
|
|
134
|
+
(compiler && compiler.stack) || []
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# A hash that contains the name of the gem for a given required file. If a
|
|
138
|
+
# `#require` fails, the gem name is looked up in this hash.
|
|
139
|
+
GEM_NAMES = {
|
|
140
|
+
'adsf' => 'adsf',
|
|
141
|
+
'bluecloth' => 'bluecloth',
|
|
142
|
+
'builder' => 'builder',
|
|
143
|
+
'coderay' => 'coderay',
|
|
144
|
+
'cri' => 'cri',
|
|
145
|
+
'erubis' => 'erubis',
|
|
146
|
+
'escape' => 'escape',
|
|
147
|
+
'fssm' => 'fssm',
|
|
148
|
+
'haml' => 'haml',
|
|
149
|
+
'json' => 'json',
|
|
150
|
+
'kramdown' => 'kramdown',
|
|
151
|
+
'less' => 'less',
|
|
152
|
+
'markaby' => 'markaby',
|
|
153
|
+
'maruku' => 'maruku',
|
|
154
|
+
'mime/types' => 'mime-types',
|
|
155
|
+
'nokogiri' => 'nokogiri',
|
|
156
|
+
'rack' => 'rack',
|
|
157
|
+
'rack/cache' => 'rack-cache',
|
|
158
|
+
'rainpress' => 'rainpress',
|
|
159
|
+
'rdiscount' => 'rdiscount',
|
|
160
|
+
'redcarpet' => 'redcarpet',
|
|
161
|
+
'redcloth' => 'redcloth',
|
|
162
|
+
'rubypants' => 'rubypants',
|
|
163
|
+
'sass' => 'sass',
|
|
164
|
+
'systemu' => 'systemu',
|
|
165
|
+
'w3c_validators' => 'w3c_validators'
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
# Attempts to find a resolution for the given error, or nil if no
|
|
169
|
+
# resolution can be automatically obtained.
|
|
170
|
+
#
|
|
171
|
+
# @param [Error] error The error to find a resolution for
|
|
172
|
+
#
|
|
173
|
+
# @return [String] The resolution for the given error
|
|
174
|
+
def resolution_for(error)
|
|
175
|
+
case error
|
|
176
|
+
when LoadError
|
|
177
|
+
# Get gem name
|
|
178
|
+
matches = error.message.match(/(no such file to load|cannot load such file) -- ([^\s]+)/)
|
|
179
|
+
return nil if matches.nil?
|
|
180
|
+
gem_name = GEM_NAMES[matches[2]]
|
|
181
|
+
|
|
182
|
+
# Build message
|
|
183
|
+
if gem_name
|
|
184
|
+
"Try installing the '#{gem_name}' gem (`gem install #{gem_name}`) and then re-running the command."
|
|
185
|
+
end
|
|
186
|
+
when RuntimeError
|
|
187
|
+
if error.message =~ /^can't modify frozen/
|
|
188
|
+
"You attempted to modify immutable data. Some data, such as " \
|
|
189
|
+
"item/layout attributes and raw item/layout content, can not " \
|
|
190
|
+
"be modified once compilation has started. (This was " \
|
|
191
|
+
"unintentionally possible in 3.1.x and before, but has been " \
|
|
192
|
+
"disabled in 3.2.x in order to allow compiler optimisations.)"
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
end
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require 'singleton'
|
|
4
|
+
|
|
5
|
+
module Nanoc::CLI
|
|
6
|
+
|
|
7
|
+
# Nanoc::CLI::Logger is a singleton class responsible for generating
|
|
8
|
+
# feedback in the terminal.
|
|
9
|
+
class Logger
|
|
10
|
+
|
|
11
|
+
# Maps actions (`:create`, `:update`, `:identical`, `:skip` and `:delete`)
|
|
12
|
+
# onto their ANSI color codes.
|
|
13
|
+
ACTION_COLORS = {
|
|
14
|
+
:create => "\e[1m" + "\e[32m", # bold + green
|
|
15
|
+
:update => "\e[1m" + "\e[33m", # bold + yellow
|
|
16
|
+
:identical => "\e[1m", # bold
|
|
17
|
+
:skip => "\e[1m", # bold
|
|
18
|
+
:delete => "\e[1m" + "\e[31m" # bold + red
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
include Singleton
|
|
22
|
+
|
|
23
|
+
# Returns the log level, which can be :high, :low or :off (which will log
|
|
24
|
+
# all messages, only high-priority messages, or no messages at all,
|
|
25
|
+
# respectively).
|
|
26
|
+
#
|
|
27
|
+
# @return [Symbol] The log level
|
|
28
|
+
attr_accessor :level
|
|
29
|
+
|
|
30
|
+
# @return [Boolean] True if color should be used, false otherwise
|
|
31
|
+
attr_writer :color
|
|
32
|
+
|
|
33
|
+
def initialize
|
|
34
|
+
@level = :high
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# @return [Boolean] true if colors are enabled, false otherwise
|
|
38
|
+
def color?
|
|
39
|
+
if @color.nil?
|
|
40
|
+
@color = true
|
|
41
|
+
begin
|
|
42
|
+
require 'Win32/Console/ANSI' if RUBY_PLATFORM =~ /mswin|mingw/
|
|
43
|
+
rescue LoadError
|
|
44
|
+
@color = false
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
@color
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Logs a file-related action.
|
|
52
|
+
#
|
|
53
|
+
# @param [:high, :low] level The importance of this action
|
|
54
|
+
#
|
|
55
|
+
# @param [:create, :update, :identical, :skip, :delete] action The kind of file action
|
|
56
|
+
#
|
|
57
|
+
# @param [String] name The name of the file the action was performed on
|
|
58
|
+
#
|
|
59
|
+
# @return [void]
|
|
60
|
+
def file(level, action, identifier, duration=nil)
|
|
61
|
+
log(
|
|
62
|
+
level,
|
|
63
|
+
'%s%12s%s %s%s' % [
|
|
64
|
+
color? ? ACTION_COLORS[action.to_sym] : '',
|
|
65
|
+
action,
|
|
66
|
+
color? ? "\e[0m" : '',
|
|
67
|
+
duration.nil? ? '' : "[%2.2fs] " % [ duration ],
|
|
68
|
+
identifier
|
|
69
|
+
]
|
|
70
|
+
)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Logs a message.
|
|
74
|
+
#
|
|
75
|
+
# @param [:high, :low] level The importance of this message
|
|
76
|
+
#
|
|
77
|
+
# @param [String] message The message to be logged
|
|
78
|
+
#
|
|
79
|
+
# @param [#puts] io The stream to which the message should be written
|
|
80
|
+
#
|
|
81
|
+
# @return [void]
|
|
82
|
+
def log(level, message, io=$stdout)
|
|
83
|
+
# Don't log when logging is disabled
|
|
84
|
+
return if @level == :off
|
|
85
|
+
|
|
86
|
+
# Log when level permits it
|
|
87
|
+
io.puts(message) if (@level == :low or @level == level)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
end
|