nanoc3 3.1.9 → 3.2.0a1
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/LICENSE +1 -1
- data/NEWS.md +0 -50
- data/README.md +3 -15
- data/bin/nanoc3 +2 -0
- data/lib/nanoc3/base/checksummer.rb +40 -0
- data/lib/nanoc3/base/code_snippet.rb +30 -12
- data/lib/nanoc3/base/compiled_content_cache.rb +86 -0
- data/lib/nanoc3/base/compiler.rb +134 -95
- data/lib/nanoc3/base/compiler_dsl.rb +12 -11
- data/lib/nanoc3/base/core_ext/string.rb +2 -2
- data/lib/nanoc3/base/data_source.rb +17 -16
- data/lib/nanoc3/base/dependency_tracker.rb +102 -121
- data/lib/nanoc3/base/directed_graph.rb +65 -3
- data/lib/nanoc3/base/errors.rb +20 -16
- data/lib/nanoc3/base/item.rb +58 -50
- data/lib/nanoc3/base/item_rep.rb +177 -150
- data/lib/nanoc3/base/layout.rb +51 -18
- data/lib/nanoc3/base/notification_center.rb +8 -8
- data/lib/nanoc3/base/plugin_registry.rb +9 -9
- data/lib/nanoc3/base/rule.rb +18 -9
- data/lib/nanoc3/base/rule_context.rb +5 -5
- data/lib/nanoc3/base/site.rb +135 -47
- data/lib/nanoc3/base.rb +21 -19
- data/lib/nanoc3/cli/base.rb +51 -74
- data/lib/nanoc3/cli/commands/autocompile.rb +3 -0
- data/lib/nanoc3/cli/commands/compile.rb +35 -74
- data/lib/nanoc3/cli/commands/create_site.rb +17 -5
- data/lib/nanoc3/cli/commands/debug.rb +11 -4
- data/lib/nanoc3/cli/commands/view.rb +0 -1
- data/lib/nanoc3/cli/commands/watch.rb +148 -0
- data/lib/nanoc3/cli/commands.rb +1 -0
- data/lib/nanoc3/cli/logger.rb +15 -21
- data/lib/nanoc3/data_sources/deprecated/twitter.rb +0 -1
- data/lib/nanoc3/data_sources/filesystem.rb +11 -40
- data/lib/nanoc3/data_sources/filesystem_unified.rb +22 -22
- data/lib/nanoc3/extra/auto_compiler.rb +1 -1
- data/lib/nanoc3/extra/chick.rb +8 -8
- data/lib/nanoc3/extra/deployers/rsync.rb +2 -3
- data/lib/nanoc3/extra/validators/links.rb +32 -51
- data/lib/nanoc3/extra/validators/w3c.rb +2 -2
- data/lib/nanoc3/extra/vcs.rb +1 -1
- data/lib/nanoc3/filters/colorize_syntax.rb +15 -19
- data/lib/nanoc3/filters/erb.rb +1 -5
- data/lib/nanoc3/filters/erubis.rb +1 -5
- data/lib/nanoc3/filters/haml.rb +1 -2
- data/lib/nanoc3/filters/less.rb +2 -51
- data/lib/nanoc3/filters/mustache.rb +21 -0
- data/lib/nanoc3/filters/rdiscount.rb +1 -2
- data/lib/nanoc3/filters/relativize_paths.rb +3 -2
- data/lib/nanoc3/filters/sass.rb +50 -56
- data/lib/nanoc3/filters.rb +2 -0
- data/lib/nanoc3/helpers/blogging.rb +22 -29
- data/lib/nanoc3/helpers/breadcrumbs.rb +1 -1
- data/lib/nanoc3/helpers/capturing.rb +1 -1
- data/lib/nanoc3/helpers/filtering.rb +1 -1
- data/lib/nanoc3/helpers/link_to.rb +10 -21
- data/lib/nanoc3/helpers/rendering.rb +5 -24
- data/lib/nanoc3/helpers/tagging.rb +6 -6
- data/lib/nanoc3/helpers/text.rb +2 -2
- data/lib/nanoc3.rb +1 -1
- metadata +35 -93
- data/.gemtest +0 -0
- data/doc/yardoc_templates/default/layout/html/footer.erb +0 -10
- data/nanoc3.gemspec +0 -41
- data/tasks/clean.rake +0 -11
- data/tasks/doc.rake +0 -14
- data/tasks/gem.rake +0 -13
- data/tasks/test.rake +0 -38
- data/test/base/core_ext/array_spec.rb +0 -23
- data/test/base/core_ext/hash_spec.rb +0 -41
- data/test/base/core_ext/string_spec.rb +0 -27
- data/test/base/test_code_snippet.rb +0 -33
- data/test/base/test_compiler.rb +0 -410
- data/test/base/test_compiler_dsl.rb +0 -121
- data/test/base/test_context.rb +0 -33
- data/test/base/test_data_source.rb +0 -48
- data/test/base/test_dependency_tracker.rb +0 -510
- data/test/base/test_directed_graph.rb +0 -91
- data/test/base/test_filter.rb +0 -85
- data/test/base/test_item.rb +0 -141
- data/test/base/test_item_rep.rb +0 -953
- data/test/base/test_layout.rb +0 -44
- data/test/base/test_notification_center.rb +0 -36
- data/test/base/test_plugin.rb +0 -32
- data/test/base/test_rule.rb +0 -21
- data/test/base/test_rule_context.rb +0 -63
- data/test/base/test_site.rb +0 -366
- data/test/cli/commands/test_compile.rb +0 -12
- data/test/cli/commands/test_create_item.rb +0 -12
- data/test/cli/commands/test_create_layout.rb +0 -28
- data/test/cli/commands/test_create_site.rb +0 -24
- data/test/cli/commands/test_help.rb +0 -12
- data/test/cli/commands/test_info.rb +0 -12
- data/test/cli/commands/test_update.rb +0 -12
- data/test/cli/test_logger.rb +0 -12
- data/test/data_sources/test_filesystem.rb +0 -420
- data/test/data_sources/test_filesystem_unified.rb +0 -538
- data/test/data_sources/test_filesystem_verbose.rb +0 -359
- data/test/extra/core_ext/test_enumerable.rb +0 -32
- data/test/extra/core_ext/test_time.rb +0 -17
- data/test/extra/deployers/test_rsync.rb +0 -234
- data/test/extra/test_auto_compiler.rb +0 -482
- data/test/extra/test_file_proxy.rb +0 -21
- data/test/extra/test_vcs.rb +0 -24
- data/test/extra/validators/test_links.rb +0 -53
- data/test/extra/validators/test_w3c.rb +0 -49
- data/test/filters/test_bluecloth.rb +0 -20
- data/test/filters/test_coderay.rb +0 -46
- data/test/filters/test_colorize_syntax.rb +0 -84
- data/test/filters/test_erb.rb +0 -72
- data/test/filters/test_erubis.rb +0 -72
- data/test/filters/test_haml.rb +0 -98
- data/test/filters/test_kramdown.rb +0 -20
- data/test/filters/test_less.rb +0 -118
- data/test/filters/test_markaby.rb +0 -26
- data/test/filters/test_maruku.rb +0 -20
- data/test/filters/test_rainpress.rb +0 -31
- data/test/filters/test_rdiscount.rb +0 -33
- data/test/filters/test_rdoc.rb +0 -18
- data/test/filters/test_redcloth.rb +0 -20
- data/test/filters/test_relativize_paths.rb +0 -231
- data/test/filters/test_rubypants.rb +0 -20
- data/test/filters/test_sass.rb +0 -235
- data/test/gem_loader.rb +0 -11
- data/test/helper.rb +0 -99
- data/test/helpers/test_blogging.rb +0 -808
- data/test/helpers/test_breadcrumbs.rb +0 -83
- data/test/helpers/test_capturing.rb +0 -42
- data/test/helpers/test_filtering.rb +0 -108
- data/test/helpers/test_html_escape.rb +0 -18
- data/test/helpers/test_link_to.rb +0 -251
- data/test/helpers/test_rendering.rb +0 -109
- data/test/helpers/test_tagging.rb +0 -89
- data/test/helpers/test_text.rb +0 -26
- data/test/helpers/test_xml_sitemap.rb +0 -69
- data/test/tasks/test_clean.rb +0 -71
data/LICENSE
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Copyright (c) 2007-
|
|
1
|
+
Copyright (c) 2007-2010 Denis Defreyne and contributors
|
|
2
2
|
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
4
|
of this software and associated documentation files (the "Software"), to deal
|
data/NEWS.md
CHANGED
|
@@ -1,55 +1,5 @@
|
|
|
1
1
|
# nanoc news
|
|
2
2
|
|
|
3
|
-
## 3.1.9 (2011-06-30)
|
|
4
|
-
|
|
5
|
-
* Really fixed dependency generation between Sass partials this time
|
|
6
|
-
* Updated Less filter to 2.0
|
|
7
|
-
* Made colorize_syntax filter throw an error if pygmentize is not available
|
|
8
|
-
|
|
9
|
-
## 3.1.8 (2011-06-25)
|
|
10
|
-
|
|
11
|
-
* Made link validator accept https: URLs
|
|
12
|
-
* Fixed erronous handling of layouts with names ending in index
|
|
13
|
-
* Fixed dependency generation between Sass partials
|
|
14
|
-
* Fixed errors related to thread requires
|
|
15
|
-
* Fixed crash while handling load errors
|
|
16
|
-
* Improved encoding handling while reading files
|
|
17
|
-
|
|
18
|
-
## 3.1.7 (2011-05-03)
|
|
19
|
-
|
|
20
|
-
* Restored compatibility with Sass 3.1
|
|
21
|
-
|
|
22
|
-
## 3.1.6 (2010-11-21)
|
|
23
|
-
|
|
24
|
-
* Fixed issues with incompatible encodings
|
|
25
|
-
|
|
26
|
-
## 3.1.5 (2010-08-24)
|
|
27
|
-
|
|
28
|
-
* Improved `#render` documentation
|
|
29
|
-
* Improved metadata section check so that e.g. raw diffs are handled properly
|
|
30
|
-
* Deprecated using `Nanoc3::Site#initialize` with a non-`"."` argument
|
|
31
|
-
* Added Ruby engine to version string
|
|
32
|
-
* Allowed the `created_at` and `updated_at` attributes used in the `Blogging`
|
|
33
|
-
helper to be `Date` instances
|
|
34
|
-
|
|
35
|
-
## 3.1.4 (2010-07-25)
|
|
36
|
-
|
|
37
|
-
* Made INT and TERM signals always quit the CLI
|
|
38
|
-
* Allowed relative imports in LESS
|
|
39
|
-
* Made sure modification times are unchanged for identical recompiled items
|
|
40
|
-
* Improved link validator error handling
|
|
41
|
-
* Made pygmentize not output extra divs and pres
|
|
42
|
-
* Allowed colorizers to be specified using symbols instead of strings
|
|
43
|
-
* Added scss to the default list of text extensions
|
|
44
|
-
|
|
45
|
-
## 3.1.3 (2010-04-25)
|
|
46
|
-
|
|
47
|
-
* Removed annoying win32console warning [Eric Sunshine]
|
|
48
|
-
* Removed color codes when not writing to a terminal, or when writing to
|
|
49
|
-
Windows’ console when win32console is not installed [Eric Sunshine]
|
|
50
|
-
* Added .xhtml and .xml to list of text extensions
|
|
51
|
-
* Improved support for relative Sass @imports [Chris Eppstein]
|
|
52
|
-
|
|
53
3
|
## 3.1.2 (2010-04-07)
|
|
54
4
|
|
|
55
5
|
* Fixed bug which could cause incorrect output when compilation of an item is
|
data/README.md
CHANGED
|
@@ -52,38 +52,26 @@ you want to explore nanoc from a technical perspective.
|
|
|
52
52
|
|
|
53
53
|
## Dependencies
|
|
54
54
|
|
|
55
|
-
nanoc
|
|
56
|
-
|
|
57
|
-
you’ll likely need some dependencies:
|
|
55
|
+
nanoc itself can be used without installing any dependencies. Some
|
|
56
|
+
components, however, do have dependencies:
|
|
58
57
|
|
|
59
|
-
* The **commandline frontend** depends on `cli`.
|
|
60
58
|
* The **autocompiler** depends on `mime-types` and `rack`.
|
|
61
|
-
* Filters and helpers likely have dependencies on their own too.
|
|
62
|
-
|
|
63
|
-
If you’re developing for nanoc, such as writing custom filters or helpers, you
|
|
64
|
-
may be interested in the development dependencies:
|
|
65
|
-
|
|
66
59
|
* For **documentation generation** you’ll need `yard`.
|
|
67
60
|
* For **packaging** you’ll need `rubygems` (1.3 or newer).
|
|
68
|
-
* For **testing** you’ll need `mocha
|
|
61
|
+
* For **testing** you’ll need `mocha`.
|
|
69
62
|
|
|
70
63
|
## Contributors
|
|
71
64
|
|
|
72
65
|
(In alphabetical order)
|
|
73
66
|
|
|
74
|
-
* Ben Armston
|
|
75
67
|
* Colin Barrett
|
|
76
68
|
* Dmitry Bilunov
|
|
77
69
|
* Brian Candler
|
|
78
70
|
* Chris Eppstein
|
|
79
|
-
* Felix Hanley
|
|
80
71
|
* Starr Horne
|
|
81
|
-
* Tuomas Kareinen
|
|
82
72
|
* Nicky Peeters
|
|
83
73
|
* Christian Plessl
|
|
84
74
|
* Šime Ramov
|
|
85
|
-
* Xavier Shay
|
|
86
|
-
* Arnau Siches
|
|
87
75
|
* “Soryu”
|
|
88
76
|
* Eric Sunshine
|
|
89
77
|
* Dennis Sutch
|
data/bin/nanoc3
CHANGED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module Nanoc3
|
|
4
|
+
|
|
5
|
+
# Responsible for creating checksums of files. Such checksums are used to
|
|
6
|
+
# determine whether files have changed between compilations.
|
|
7
|
+
class Checksummer
|
|
8
|
+
|
|
9
|
+
# Returns a checksum for the specified file. Multiple invocations of this
|
|
10
|
+
# method with the same filename argument will yield the same result.
|
|
11
|
+
#
|
|
12
|
+
# The returned checksum has the property that for two given files with
|
|
13
|
+
# different content, the returned checksum will be different with a very
|
|
14
|
+
# high probability. In practice, this boils down to using a secure
|
|
15
|
+
# cryptographic hash function, such as SHA-1.
|
|
16
|
+
#
|
|
17
|
+
# The format of the resulting checksum should not be relied upon. In
|
|
18
|
+
# future versions of nanoc, this function may use a different method for
|
|
19
|
+
# generating checksums.
|
|
20
|
+
#
|
|
21
|
+
# @param [String] filename The name of the file for which the checksum
|
|
22
|
+
# should be calculated
|
|
23
|
+
#
|
|
24
|
+
# @return [String] The checksum for the given files
|
|
25
|
+
def self.checksum_for(filename)
|
|
26
|
+
require 'digest'
|
|
27
|
+
|
|
28
|
+
digest = Digest::SHA1.new
|
|
29
|
+
File.open(filename, 'r') do |io|
|
|
30
|
+
until io.eof
|
|
31
|
+
data = io.readpartial(2**10)
|
|
32
|
+
digest.update(data)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
digest.hexdigest
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
end
|
|
@@ -2,9 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
module Nanoc3
|
|
4
4
|
|
|
5
|
-
# Nanoc3::CodeSnippet represent a piece of custom code of a nanoc site.
|
|
6
|
-
# contains the textual source code as well as a mtime, which is used to
|
|
7
|
-
# speed up site compilation.
|
|
5
|
+
# Nanoc3::CodeSnippet represent a piece of custom code of a nanoc site.
|
|
8
6
|
class CodeSnippet
|
|
9
7
|
|
|
10
8
|
# The {Nanoc3::Site} this code snippet belongs to.
|
|
@@ -22,24 +20,38 @@ module Nanoc3
|
|
|
22
20
|
# @return [String]
|
|
23
21
|
attr_reader :filename
|
|
24
22
|
|
|
25
|
-
# The
|
|
26
|
-
#
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
# @return [String] The checksum of this code snippet that was in effect
|
|
24
|
+
# during the previous site compilation
|
|
25
|
+
attr_accessor :old_checksum
|
|
26
|
+
|
|
27
|
+
# @return [String] The current, up-to-date checksum of this code snippet
|
|
28
|
+
attr_reader :new_checksum
|
|
29
29
|
|
|
30
30
|
# Creates a new code snippet.
|
|
31
31
|
#
|
|
32
32
|
# @param [String] data The raw source code which will be executed before
|
|
33
|
-
#
|
|
33
|
+
# compilation
|
|
34
34
|
#
|
|
35
35
|
# @param [String] filename The filename corresponding to this code snippet
|
|
36
36
|
#
|
|
37
|
-
# @param [Time]
|
|
38
|
-
#
|
|
39
|
-
|
|
37
|
+
# @param [Time, Hash] params Extra parameters. For backwards
|
|
38
|
+
# compatibility, this can be a Time instance indicating the time when
|
|
39
|
+
# this code snippet was last modified (mtime).
|
|
40
|
+
#
|
|
41
|
+
# @option params [Time, nil] :mtime (nil) The time when this code snippet
|
|
42
|
+
# was last modified
|
|
43
|
+
#
|
|
44
|
+
# @option params [String, nil] :checksum (nil) The current, up-to-date
|
|
45
|
+
# checksum of this code snippet
|
|
46
|
+
def initialize(data, filename, params=nil)
|
|
47
|
+
# Get mtime and checksum
|
|
48
|
+
params ||= {}
|
|
49
|
+
params = { :mtime => params } if params.is_a?(Time)
|
|
50
|
+
@new_checksum = params[:checksum]
|
|
51
|
+
@mtime = params[:mtime]
|
|
52
|
+
|
|
40
53
|
@data = data
|
|
41
54
|
@filename = filename
|
|
42
|
-
@mtime = mtime
|
|
43
55
|
end
|
|
44
56
|
|
|
45
57
|
# Loads the code by executing it.
|
|
@@ -49,6 +61,12 @@ module Nanoc3
|
|
|
49
61
|
eval(@data, TOPLEVEL_BINDING, @filename)
|
|
50
62
|
end
|
|
51
63
|
|
|
64
|
+
# @return [Boolean] true if the code snippet was modified since it was
|
|
65
|
+
# last compiled, false otherwise
|
|
66
|
+
def outdated?
|
|
67
|
+
!self.old_checksum || !self.new_checksum || self.new_checksum != self.old_checksum
|
|
68
|
+
end
|
|
69
|
+
|
|
52
70
|
end
|
|
53
71
|
|
|
54
72
|
end
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module Nanoc3
|
|
4
|
+
|
|
5
|
+
# Represents a cache than can be used to store already compiled content,
|
|
6
|
+
# to prevent it from being needlessly recompiled.
|
|
7
|
+
#
|
|
8
|
+
# This class is intended for internal use only. Do not rely on its
|
|
9
|
+
# presence; future versions of nanoc, even in the 3.x branch, may no
|
|
10
|
+
# longer contain this class.
|
|
11
|
+
class CompiledContentCache
|
|
12
|
+
|
|
13
|
+
# @return [String] The filename where the cache will be loaded from
|
|
14
|
+
# and stored to
|
|
15
|
+
attr_reader :filename
|
|
16
|
+
|
|
17
|
+
# Creates a new cache for the given filename.
|
|
18
|
+
#
|
|
19
|
+
# @param [String] filename The filename where the cache will be loaded
|
|
20
|
+
# from and stored to
|
|
21
|
+
def initialize(filename)
|
|
22
|
+
require 'pstore'
|
|
23
|
+
|
|
24
|
+
@filename = filename
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Loads the cache from the filesystem into memory.
|
|
28
|
+
#
|
|
29
|
+
# @return [void]
|
|
30
|
+
def load
|
|
31
|
+
cache = nil
|
|
32
|
+
return if !File.file?(filename)
|
|
33
|
+
pstore.transaction { cache = pstore[:compiled_content] }
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Stores the content of the (probably modified) in-memory cache to the
|
|
37
|
+
# filesystem.
|
|
38
|
+
#
|
|
39
|
+
# @return [void]
|
|
40
|
+
def store
|
|
41
|
+
FileUtils.mkdir_p(File.dirname(filename))
|
|
42
|
+
pstore.transaction { pstore[:compiled_content] = cache }
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Returns the cached compiled content for the given item
|
|
46
|
+
# representation. This cached compiled content is a hash where the keys
|
|
47
|
+
# are the snapshot names and the values the compiled content at the
|
|
48
|
+
# given snapshot.
|
|
49
|
+
#
|
|
50
|
+
# @param [Nanoc3::ItemRep] rep The item rep to fetch the content for
|
|
51
|
+
#
|
|
52
|
+
# @return [Hash<Symbol,String>] A hash containing the cached compiled
|
|
53
|
+
# content for the given item representation
|
|
54
|
+
def [](rep)
|
|
55
|
+
item_cache = cache[rep.item.identifier] || {}
|
|
56
|
+
item_cache[rep.name]
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Sets the compiled content for the given representation.
|
|
60
|
+
#
|
|
61
|
+
# @param [Nanoc3::ItemRep] rep The item representation for which to set
|
|
62
|
+
# the compiled content
|
|
63
|
+
#
|
|
64
|
+
# @param [Hash<Symbol,String>] content A hash containing the compiled
|
|
65
|
+
# content of the given representation
|
|
66
|
+
#
|
|
67
|
+
# @return [void]
|
|
68
|
+
def []=(rep, content)
|
|
69
|
+
cache[rep.item.identifier] ||= {}
|
|
70
|
+
cache[rep.item.identifier][rep.name] = content
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
private
|
|
74
|
+
|
|
75
|
+
def cache
|
|
76
|
+
@cache ||= {}
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def pstore
|
|
80
|
+
require 'pstore'
|
|
81
|
+
@store ||= PStore.new(@filename)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
end
|
data/lib/nanoc3/base/compiler.rb
CHANGED
|
@@ -3,8 +3,38 @@
|
|
|
3
3
|
module Nanoc3
|
|
4
4
|
|
|
5
5
|
# Responsible for compiling a site’s item representations.
|
|
6
|
+
#
|
|
7
|
+
# The compilation process makes use of notifications (see
|
|
8
|
+
# {Nanoc3::NotificationCenter}) to track dependencies between items,
|
|
9
|
+
# layouts, etc. The following notifications are used:
|
|
10
|
+
#
|
|
11
|
+
# * `compilation_started` — indicates that the compiler has started
|
|
12
|
+
# compiling this item representation. Has one argument: the item
|
|
13
|
+
# representation itself. Only one item can be compiled at a given moment;
|
|
14
|
+
# therefore, it is not possible to get two consecutive
|
|
15
|
+
# `compilation_started` notifications without also getting a
|
|
16
|
+
# `compilation_ended` notification in between them.
|
|
17
|
+
#
|
|
18
|
+
# * `compilation_ended` — indicates that the compiler has finished compiling
|
|
19
|
+
# this item representation (either successfully or with failure). Has one
|
|
20
|
+
# argument: the item representation itself.
|
|
21
|
+
#
|
|
22
|
+
# * `visit_started` — indicates that the compiler requires content or
|
|
23
|
+
# attributes from the item representation that will be visited. Has one
|
|
24
|
+
# argument: the visited item identifier. This notification is used to
|
|
25
|
+
# track dependencies of items on other items; a `visit_started` event
|
|
26
|
+
# followed by another `visit_started` event indicates that the item
|
|
27
|
+
# corresponding to the former event will depend on the item from the
|
|
28
|
+
# latter event.
|
|
29
|
+
#
|
|
30
|
+
# * `visit_ended` — indicates that the compiler has finished visiting the
|
|
31
|
+
# item representation and that the requested attributes or content have
|
|
32
|
+
# been fetched (either successfully or with failure)
|
|
6
33
|
class Compiler
|
|
7
34
|
|
|
35
|
+
# The name of the file where cached compiled content will be stored
|
|
36
|
+
COMPILED_CONTENT_CACHE_FILENAME = 'tmp/compiled_content'
|
|
37
|
+
|
|
8
38
|
# The compilation stack. When the compiler begins compiling a rep or a
|
|
9
39
|
# layout, it will be placed on the stack; when it is done compiling the
|
|
10
40
|
# rep or layout, it will be removed from the stack.
|
|
@@ -47,34 +77,31 @@ module Nanoc3
|
|
|
47
77
|
# representations.
|
|
48
78
|
#
|
|
49
79
|
# @param [Nanoc3::Item] item The item that should be compiled, along with
|
|
50
|
-
#
|
|
80
|
+
# its dependencies. Pass `nil` if the entire site should be compiled.
|
|
51
81
|
#
|
|
52
82
|
# @option params [Boolean] :force (false) true if the rep should be
|
|
53
|
-
#
|
|
83
|
+
# compiled even if it is not outdated, false if not
|
|
54
84
|
#
|
|
55
85
|
# @return [void]
|
|
56
86
|
def run(item=nil, params={})
|
|
87
|
+
# Parse params
|
|
88
|
+
params[:force] = false if !params.has_key?(:force)
|
|
89
|
+
|
|
57
90
|
# Create output directory if necessary
|
|
58
91
|
FileUtils.mkdir_p(@site.config[:output_dir])
|
|
59
92
|
|
|
60
|
-
# Load
|
|
93
|
+
# Load necessary data
|
|
94
|
+
compiled_content_cache = CompiledContentCache.new(COMPILED_CONTENT_CACHE_FILENAME)
|
|
95
|
+
compiled_content_cache.load
|
|
61
96
|
dependency_tracker.load_graph
|
|
62
97
|
|
|
63
98
|
# Get items and reps to compile
|
|
64
|
-
|
|
65
|
-
items = [ item ] + dependency_tracker.successors_of(item)
|
|
66
|
-
items.uniq!
|
|
67
|
-
else
|
|
68
|
-
items = @site.items
|
|
69
|
-
end
|
|
99
|
+
items = item ? ([ item ] + dependency_tracker.successors_of(item)).uniq : @site.items
|
|
70
100
|
reps = items.map { |i| i.reps }.flatten
|
|
71
101
|
|
|
72
|
-
#
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
else
|
|
76
|
-
dependency_tracker.propagate_outdatedness
|
|
77
|
-
end
|
|
102
|
+
# Determine which reps need to be recompiled
|
|
103
|
+
reps.each { |r| r.force_outdated = true } if params[:force]
|
|
104
|
+
dependency_tracker.propagate_outdatedness
|
|
78
105
|
forget_dependencies_if_outdated(items)
|
|
79
106
|
|
|
80
107
|
# Compile reps
|
|
@@ -82,11 +109,21 @@ module Nanoc3
|
|
|
82
109
|
compile_reps(reps)
|
|
83
110
|
dependency_tracker.stop
|
|
84
111
|
|
|
112
|
+
# Store necessary data
|
|
113
|
+
compiled_content_cache.store
|
|
114
|
+
@site.store_checksums
|
|
115
|
+
dependency_tracker.store_graph
|
|
116
|
+
ensure
|
|
85
117
|
# Cleanup
|
|
86
118
|
FileUtils.rm_rf(Nanoc3::Filter::TMP_BINARY_ITEMS_DIR)
|
|
119
|
+
end
|
|
87
120
|
|
|
88
|
-
|
|
89
|
-
|
|
121
|
+
# Returns the dependency tracker for this site, creating it first if it
|
|
122
|
+
# does not yet exist.
|
|
123
|
+
#
|
|
124
|
+
# @return [Nanoc3::DependencyTracker] The dependency tracker for this site
|
|
125
|
+
def dependency_tracker
|
|
126
|
+
@dependency_tracker ||= Nanoc3::DependencyTracker.new(@site.items + @site.layouts)
|
|
90
127
|
end
|
|
91
128
|
|
|
92
129
|
# Finds the first matching compilation rule for the given item
|
|
@@ -95,7 +132,7 @@ module Nanoc3
|
|
|
95
132
|
# @param [Nanoc3::ItemRep] rep The item rep for which to fetch the rule
|
|
96
133
|
#
|
|
97
134
|
# @return [Nanoc3::Rule, nil] The compilation rule for the given item rep,
|
|
98
|
-
#
|
|
135
|
+
# or nil if no rules have been found
|
|
99
136
|
def compilation_rule_for(rep)
|
|
100
137
|
@item_compilation_rules.find do |rule|
|
|
101
138
|
rule.applicable_to?(rep.item) && rule.rep_name == rep.name
|
|
@@ -107,19 +144,37 @@ module Nanoc3
|
|
|
107
144
|
# @param [Nanoc3::ItemRep] rep The item rep for which to fetch the rule
|
|
108
145
|
#
|
|
109
146
|
# @return [Nanoc3::Rule, nil] The routing rule for the given item rep, or
|
|
110
|
-
#
|
|
147
|
+
# nil if no rules have been found
|
|
111
148
|
def routing_rule_for(rep)
|
|
112
149
|
@item_routing_rules.find do |rule|
|
|
113
150
|
rule.applicable_to?(rep.item) && rule.rep_name == rep.name
|
|
114
151
|
end
|
|
115
152
|
end
|
|
116
153
|
|
|
154
|
+
# Returns the list of routing rules that can be applied to the given item
|
|
155
|
+
# representation. For each snapshot, the first matching rule will be
|
|
156
|
+
# returned. The result is a hash containing the corresponding rule for
|
|
157
|
+
# each snapshot.
|
|
158
|
+
#
|
|
159
|
+
# @return [Hash<Symbol, Nanoc3::Rule>] The routing rules for the given rep
|
|
160
|
+
def routing_rules_for(rep)
|
|
161
|
+
rules = {}
|
|
162
|
+
@item_routing_rules.each do |rule|
|
|
163
|
+
next if !rule.applicable_to?(rep.item)
|
|
164
|
+
next if rule.rep_name != rep.name
|
|
165
|
+
next if rules.has_key?(rule.snapshot_name)
|
|
166
|
+
|
|
167
|
+
rules[rule.snapshot_name] = rule
|
|
168
|
+
end
|
|
169
|
+
rules
|
|
170
|
+
end
|
|
171
|
+
|
|
117
172
|
# Finds the filter name and arguments to use for the given layout.
|
|
118
173
|
#
|
|
119
174
|
# @param [Nanoc3::Layout] layout The layout for which to fetch the filter.
|
|
120
175
|
#
|
|
121
176
|
# @return [Array, nil] A tuple containing the filter name and the filter
|
|
122
|
-
#
|
|
177
|
+
# arguments for the given layout.
|
|
123
178
|
def filter_for_layout(layout)
|
|
124
179
|
@layout_filter_mapping.each_pair do |layout_identifier, filter_name_and_args|
|
|
125
180
|
return filter_name_and_args if layout.identifier =~ layout_identifier
|
|
@@ -135,69 +190,41 @@ module Nanoc3
|
|
|
135
190
|
#
|
|
136
191
|
# @return [void]
|
|
137
192
|
def compile_reps(reps)
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
# Attempt to compile all active reps
|
|
148
|
-
until active_reps.empty?
|
|
149
|
-
@stack.clear
|
|
150
|
-
begin
|
|
151
|
-
rep = active_reps.shift
|
|
152
|
-
puts "*** Attempting to compile #{rep.inspect}" if $DEBUG
|
|
153
|
-
|
|
154
|
-
@stack.push(rep)
|
|
155
|
-
compile_rep(rep)
|
|
156
|
-
rescue Nanoc3::Errors::UnmetDependency => e
|
|
157
|
-
puts "*** Attempt failed due to unmet dependency on #{e.rep.inspect}" if $DEBUG
|
|
158
|
-
|
|
159
|
-
# Reinitialize rep
|
|
160
|
-
rep.forget_progress
|
|
161
|
-
|
|
162
|
-
# Save rep to compile it later
|
|
163
|
-
inactive_reps << rep
|
|
164
|
-
|
|
165
|
-
# Add dependency to list of items to compile
|
|
166
|
-
unless active_reps.include?(e.rep) || inactive_reps.include?(e.rep)
|
|
167
|
-
changed = true
|
|
168
|
-
skipped_reps.delete(e.rep)
|
|
169
|
-
inactive_reps.unshift(e.rep)
|
|
170
|
-
end
|
|
171
|
-
else
|
|
172
|
-
puts "*** Attempt succeeded" if $DEBUG
|
|
173
|
-
|
|
174
|
-
changed = true
|
|
175
|
-
compiled_reps << rep
|
|
176
|
-
end
|
|
177
|
-
puts if $DEBUG
|
|
178
|
-
end
|
|
179
|
-
|
|
180
|
-
# Retry
|
|
181
|
-
if inactive_reps.empty?
|
|
182
|
-
puts "*** Nothing left to compile!" if $DEBUG
|
|
183
|
-
break
|
|
184
|
-
else
|
|
185
|
-
puts "*** No active reps left; activating all (#{inactive_reps.size}) inactive reps" if $DEBUG
|
|
186
|
-
puts if $DEBUG
|
|
187
|
-
active_reps = inactive_reps
|
|
188
|
-
inactive_reps = []
|
|
189
|
-
end
|
|
193
|
+
require 'set'
|
|
194
|
+
|
|
195
|
+
# Partition in outdated and non-outdated
|
|
196
|
+
outdated_reps = Set.new
|
|
197
|
+
skipped_reps = Set.new
|
|
198
|
+
reps.each do |rep|
|
|
199
|
+
target = (rep.outdated? || rep.item.outdated_due_to_dependencies?) ? outdated_reps : skipped_reps
|
|
200
|
+
target.add(rep)
|
|
190
201
|
end
|
|
191
202
|
|
|
192
|
-
#
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
203
|
+
# Build graph for outdated reps
|
|
204
|
+
content_dependency_graph = Nanoc3::DirectedGraph.new(outdated_reps)
|
|
205
|
+
|
|
206
|
+
# Attempt to compile all active reps
|
|
207
|
+
loop do
|
|
208
|
+
# Find rep to compile
|
|
209
|
+
break if content_dependency_graph.roots.empty?
|
|
210
|
+
rep = content_dependency_graph.roots.each { |e| break e }
|
|
211
|
+
@stack = [ rep ]
|
|
212
|
+
|
|
213
|
+
begin
|
|
214
|
+
compile_rep(rep)
|
|
215
|
+
content_dependency_graph.delete_vertex(rep)
|
|
216
|
+
rescue Nanoc3::Errors::UnmetDependency => e
|
|
217
|
+
content_dependency_graph.add_edge(e.rep, rep)
|
|
218
|
+
unless content_dependency_graph.vertices.include?(e.rep)
|
|
219
|
+
skipped_reps.delete(e.rep)
|
|
220
|
+
content_dependency_graph.add_vertex(e.rep)
|
|
221
|
+
end
|
|
222
|
+
end
|
|
196
223
|
end
|
|
197
224
|
|
|
198
|
-
#
|
|
199
|
-
if !
|
|
200
|
-
raise Nanoc3::Errors::RecursiveCompilation.new(
|
|
225
|
+
# Check whether everything was compiled
|
|
226
|
+
if !content_dependency_graph.vertices.empty?
|
|
227
|
+
raise Nanoc3::Errors::RecursiveCompilation.new(content_dependency_graph.vertices)
|
|
201
228
|
end
|
|
202
229
|
end
|
|
203
230
|
|
|
@@ -211,34 +238,35 @@ module Nanoc3
|
|
|
211
238
|
#
|
|
212
239
|
# @return [void]
|
|
213
240
|
def compile_rep(rep)
|
|
214
|
-
# Start
|
|
215
241
|
Nanoc3::NotificationCenter.post(:compilation_started, rep)
|
|
216
242
|
Nanoc3::NotificationCenter.post(:visit_started, rep.item)
|
|
217
243
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
244
|
+
if !rep.outdated? && !rep.item.outdated_due_to_dependencies && compiled_content_cache[rep]
|
|
245
|
+
Nanoc3::NotificationCenter.post(:cached_content_used, rep)
|
|
246
|
+
rep.content = compiled_content_cache[rep]
|
|
247
|
+
else
|
|
248
|
+
rep.snapshot(:raw)
|
|
249
|
+
rep.snapshot(:pre, :final => false)
|
|
250
|
+
compilation_rule_for(rep).apply_to(rep)
|
|
251
|
+
rep.snapshot(:post) if rep.has_snapshot?(:post)
|
|
252
|
+
rep.snapshot(:last)
|
|
253
|
+
end
|
|
221
254
|
|
|
222
|
-
|
|
223
|
-
rep
|
|
255
|
+
rep.compiled = true
|
|
256
|
+
compiled_content_cache[rep] = rep.content
|
|
257
|
+
rescue => e
|
|
258
|
+
rep.forget_progress
|
|
259
|
+
Nanoc3::NotificationCenter.post(:compilation_failed, rep)
|
|
260
|
+
raise e
|
|
224
261
|
ensure
|
|
225
|
-
# Stop
|
|
226
262
|
Nanoc3::NotificationCenter.post(:visit_ended, rep.item)
|
|
227
263
|
Nanoc3::NotificationCenter.post(:compilation_ended, rep)
|
|
228
264
|
end
|
|
229
265
|
|
|
230
|
-
# Returns the dependency tracker for this site, creating it first if it
|
|
231
|
-
# does not yet exist.
|
|
232
|
-
#
|
|
233
|
-
# @return [Nanoc3::DependencyTracker] The dependency tracker for this site
|
|
234
|
-
def dependency_tracker
|
|
235
|
-
@dependency_tracker ||= Nanoc3::DependencyTracker.new(@site.items)
|
|
236
|
-
end
|
|
237
|
-
|
|
238
266
|
# Clears the list of dependencies for items that will be recompiled.
|
|
239
267
|
#
|
|
240
268
|
# @param [Array<Nanoc3::Item>] items The list of items for which to forget
|
|
241
|
-
#
|
|
269
|
+
# the dependencies
|
|
242
270
|
#
|
|
243
271
|
# @return [void]
|
|
244
272
|
def forget_dependencies_if_outdated(items)
|
|
@@ -249,6 +277,17 @@ module Nanoc3
|
|
|
249
277
|
end
|
|
250
278
|
end
|
|
251
279
|
|
|
280
|
+
# Returns the cache used for storing compiled content.
|
|
281
|
+
#
|
|
282
|
+
# @return [CompiledContentCache] The compiled content cache
|
|
283
|
+
def compiled_content_cache
|
|
284
|
+
@compiled_content_cache ||= begin
|
|
285
|
+
cache = Nanoc3::CompiledContentCache.new(COMPILED_CONTENT_CACHE_FILENAME)
|
|
286
|
+
cache.load
|
|
287
|
+
cache
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
|
|
252
291
|
end
|
|
253
292
|
|
|
254
293
|
end
|