nanoc-core 4.11.12 → 4.11.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/lib/nanoc/core.rb +37 -0
  3. data/lib/nanoc/core/basic_item_rep_collection_view.rb +88 -0
  4. data/lib/nanoc/core/basic_item_rep_view.rb +83 -0
  5. data/lib/nanoc/core/basic_item_view.rb +54 -0
  6. data/lib/nanoc/core/checksummer.rb +2 -0
  7. data/lib/nanoc/core/compilation_item_rep_collection_view.rb +12 -0
  8. data/lib/nanoc/core/compilation_item_rep_view.rb +51 -0
  9. data/lib/nanoc/core/compilation_item_view.rb +47 -0
  10. data/lib/nanoc/core/compilation_phases/abstract.rb +48 -0
  11. data/lib/nanoc/core/compilation_phases/cache.rb +43 -0
  12. data/lib/nanoc/core/compilation_phases/mark_done.rb +23 -0
  13. data/lib/nanoc/core/compilation_phases/notify.rb +19 -0
  14. data/lib/nanoc/core/compilation_phases/recalculate.rb +49 -0
  15. data/lib/nanoc/core/compilation_phases/resume.rb +52 -0
  16. data/lib/nanoc/core/compilation_phases/write.rb +84 -0
  17. data/lib/nanoc/core/compilation_stages/build_reps.rb +36 -0
  18. data/lib/nanoc/core/compilation_stages/calculate_checksums.rb +42 -0
  19. data/lib/nanoc/core/compilation_stages/cleanup.rb +43 -0
  20. data/lib/nanoc/core/compilation_stages/compile_reps.rb +96 -0
  21. data/lib/nanoc/core/compilation_stages/determine_outdatedness.rb +49 -0
  22. data/lib/nanoc/core/compilation_stages/forget_outdated_dependencies.rb +20 -0
  23. data/lib/nanoc/core/compilation_stages/load_stores.rb +35 -0
  24. data/lib/nanoc/core/compilation_stages/postprocess.rb +21 -0
  25. data/lib/nanoc/core/compilation_stages/preprocess.rb +32 -0
  26. data/lib/nanoc/core/compilation_stages/prune.rb +30 -0
  27. data/lib/nanoc/core/compilation_stages/store_post_compilation_state.rb +20 -0
  28. data/lib/nanoc/core/compilation_stages/store_pre_compilation_state.rb +32 -0
  29. data/lib/nanoc/core/compiler.rb +214 -0
  30. data/lib/nanoc/core/compiler_loader.rb +48 -0
  31. data/lib/nanoc/core/config_loader.rb +95 -0
  32. data/lib/nanoc/core/config_view.rb +67 -0
  33. data/lib/nanoc/core/configuration.rb +2 -4
  34. data/lib/nanoc/core/document_view_mixin.rb +87 -0
  35. data/lib/nanoc/core/errors.rb +97 -0
  36. data/lib/nanoc/core/executor.rb +134 -0
  37. data/lib/nanoc/core/feature.rb +92 -0
  38. data/lib/nanoc/core/filter.rb +269 -0
  39. data/lib/nanoc/core/identifiable_collection_view.rb +111 -0
  40. data/lib/nanoc/core/item_collection_with_reps_view.rb +12 -0
  41. data/lib/nanoc/core/item_collection_without_reps_view.rb +12 -0
  42. data/lib/nanoc/core/item_rep_builder.rb +54 -0
  43. data/lib/nanoc/core/item_rep_selector.rb +67 -0
  44. data/lib/nanoc/core/item_rep_writer.rb +85 -0
  45. data/lib/nanoc/core/layout_collection_view.rb +12 -0
  46. data/lib/nanoc/core/layout_view.rb +9 -0
  47. data/lib/nanoc/core/mutable_config_view.rb +16 -0
  48. data/lib/nanoc/core/mutable_document_view_mixin.rb +60 -0
  49. data/lib/nanoc/core/mutable_identifiable_collection_view.rb +19 -0
  50. data/lib/nanoc/core/mutable_item_collection_view.rb +34 -0
  51. data/lib/nanoc/core/mutable_item_view.rb +9 -0
  52. data/lib/nanoc/core/mutable_layout_collection_view.rb +26 -0
  53. data/lib/nanoc/core/mutable_layout_view.rb +9 -0
  54. data/lib/nanoc/core/outdatedness_checker.rb +222 -0
  55. data/lib/nanoc/core/outdatedness_rules/attributes_modified.rb +41 -0
  56. data/lib/nanoc/core/outdatedness_rules/code_snippets_modified.rb +31 -0
  57. data/lib/nanoc/core/outdatedness_rules/content_modified.rb +21 -0
  58. data/lib/nanoc/core/outdatedness_rules/item_collection_extended.rb +20 -0
  59. data/lib/nanoc/core/outdatedness_rules/layout_collection_extended.rb +20 -0
  60. data/lib/nanoc/core/outdatedness_rules/not_written.rb +17 -0
  61. data/lib/nanoc/core/outdatedness_rules/rules_modified.rb +45 -0
  62. data/lib/nanoc/core/outdatedness_rules/uses_always_outdated_filter.rb +26 -0
  63. data/lib/nanoc/core/post_compile_item_collection_view.rb +12 -0
  64. data/lib/nanoc/core/post_compile_item_rep_collection_view.rb +12 -0
  65. data/lib/nanoc/core/post_compile_item_rep_view.rb +33 -0
  66. data/lib/nanoc/core/post_compile_item_view.rb +20 -0
  67. data/lib/nanoc/core/pruner.rb +119 -0
  68. data/lib/nanoc/core/site_loader.rb +102 -0
  69. data/lib/nanoc/core/trivial_error.rb +10 -0
  70. data/lib/nanoc/core/version.rb +1 -1
  71. data/lib/nanoc/core/view.rb +43 -0
  72. data/lib/nanoc/core/view_context_for_compilation.rb +6 -6
  73. metadata +95 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bf201905e79de9d9711910668d228863a48b53e13a78694a50122932960d6189
4
- data.tar.gz: ffae70af266ec5c189b0d09976bfb9ebada587f5ea1eeb73b12dfeaebeb07d36
3
+ metadata.gz: e0e2dd5ec7f304ce59ed69129bf291b1be44dfd01740ab59634a7f3f1033ad43
4
+ data.tar.gz: dc054fcd938d0980cab9699705b622b5cff901631bc69f9aa89fae08a42c7239
5
5
  SHA512:
6
- metadata.gz: bf812e2fc282b019b2d907ee39a84fe7999b2b2f8565139cc442e3ca38cb75949ea70f27b07058ef4bd52af9a1291c0ca73e6db53790e431976a729f6a4dd3c8
7
- data.tar.gz: ef670404975dfde21013d6878afbf272e7bd41d7dee120e124cb2c61e37e1ad1f5ac64ccc1f4554f57dcde1d1303cac32ef6e088853d569c24f1c070c72abc7c
6
+ metadata.gz: 2030d8250adaeb13cc7974cf35cada04e0c6ec8a7c62e81382ca0f808dfd8e6a3b0e719ffc3bdb4131236bbbfb730e122fa4779b447bc386487f588bc90a5e01
7
+ data.tar.gz: ec172cf7c9d17bcfc399212e855cc4c5dfbf9cc627b48ead86e0fe9ff264f79a67d90089f3ead1a1cbf1ba363858974ef9eb276b198e3060a27905cd5542c419
@@ -1,9 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Ruby stdlib
4
+ require 'fiber'
5
+ require 'find'
4
6
  require 'pstore'
5
7
  require 'singleton'
6
8
  require 'tmpdir'
9
+ require 'yaml'
7
10
 
8
11
  # External gems
9
12
  require 'json_schema'
@@ -12,10 +15,32 @@ require 'ddmetrics'
12
15
  require 'ddplugin'
13
16
  require 'hamster'
14
17
  require 'slow_enumerator_tools'
18
+ require 'tomlrb'
19
+ require 'tty-platform'
15
20
  require 'zeitwerk'
16
21
 
17
22
  module Nanoc
18
23
  module Core
24
+ # Similar to `nil` except that it can only be compared against using
25
+ # `UNDEFINED.equal?(x)`. Used in places where `nil` already has meaning, and
26
+ # thus cannot be used to mean the presence of nothing.
27
+ UNDEFINED = Object.new
28
+
29
+ # @return [String] A string containing information about this Nanoc version
30
+ # and its environment (Ruby engine and version, Rubygems version if any).
31
+ #
32
+ # @api private
33
+ def self.version_information
34
+ "Nanoc #{Nanoc::VERSION} © 2007–2019 Denis Defreyne.\n" \
35
+ "Running #{RUBY_ENGINE} #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) on #{RUBY_PLATFORM} with RubyGems #{Gem::VERSION}.\n"
36
+ end
37
+
38
+ # @return [Boolean] True if the current platform is Windows, false otherwise.
39
+ #
40
+ # @api private
41
+ def self.on_windows?
42
+ @_on_windows ||= TTY::Platform.new.windows?
43
+ end
19
44
  end
20
45
  end
21
46
 
@@ -43,3 +68,15 @@ loader.eager_load
43
68
  require_relative 'core/core_ext/array'
44
69
  require_relative 'core/core_ext/hash'
45
70
  require_relative 'core/core_ext/string'
71
+
72
+ # Tracking issue:
73
+ # https://github.com/nanoc/features/issues/24
74
+ Nanoc::Core::Feature.define('live_cmd', version: '4.11')
75
+
76
+ # Tracking issue:
77
+ # https://github.com/nanoc/features/issues/40
78
+ Nanoc::Core::Feature.define('toml', version: '4.11')
79
+
80
+ # Tracking issue:
81
+ # https://github.com/nanoc/features/issues/20
82
+ Nanoc::Core::Feature.define('binary_compiled_content_cache', version: '4.11')
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nanoc
4
+ module Core
5
+ class BasicItemRepCollectionView < ::Nanoc::Core::View
6
+ include Enumerable
7
+
8
+ class NoSuchItemRepError < ::Nanoc::Core::Error
9
+ def initialize(rep_name)
10
+ super("No rep named #{rep_name.inspect} was found.")
11
+ end
12
+ end
13
+
14
+ # @api private
15
+ def initialize(item_reps, context)
16
+ super(context)
17
+ @item_reps = item_reps
18
+ end
19
+
20
+ # @api private
21
+ def _unwrap
22
+ @item_reps
23
+ end
24
+
25
+ # @api private
26
+ def view_class
27
+ Nanoc::Core::BasicItemRepView
28
+ end
29
+
30
+ def to_ary
31
+ @item_reps.map { |ir| view_class.new(ir, @context) }
32
+ end
33
+
34
+ # Calls the given block once for each item rep, passing that item rep as a parameter.
35
+ #
36
+ # @yieldparam [Object] item rep view
37
+ #
38
+ # @yieldreturn [void]
39
+ #
40
+ # @return [self]
41
+ def each
42
+ @item_reps.each { |ir| yield view_class.new(ir, @context) }
43
+ self
44
+ end
45
+
46
+ # @return [Integer]
47
+ def size
48
+ @item_reps.size
49
+ end
50
+
51
+ # Return the item rep with the given name, or nil if no item rep exists.
52
+ #
53
+ # @param [Symbol] rep_name
54
+ #
55
+ # @return [nil] if no item rep with the given name was found
56
+ #
57
+ # @return [Nanoc::Core::BasicItemRepView] if an item rep with the given name was found
58
+ def [](rep_name)
59
+ case rep_name
60
+ when Symbol
61
+ res = @item_reps.find { |ir| ir.name == rep_name }
62
+ res && view_class.new(res, @context)
63
+ when Integer
64
+ raise ArgumentError, "expected BasicItemRepCollectionView#[] to be called with a symbol (you likely want `.reps[:default]` rather than `.reps[#{rep_name}]`)"
65
+ else
66
+ raise ArgumentError, 'expected BasicItemRepCollectionView#[] to be called with a symbol'
67
+ end
68
+ end
69
+
70
+ # Return the item rep with the given name, or raises an exception if there
71
+ # is no rep with the given name.
72
+ #
73
+ # @param [Symbol] rep_name
74
+ #
75
+ # @return [Nanoc::Core::BasicItemRepView]
76
+ #
77
+ # @raise if no rep was found
78
+ def fetch(rep_name)
79
+ res = @item_reps.find { |ir| ir.name == rep_name }
80
+ if res
81
+ view_class.new(res, @context)
82
+ else
83
+ raise NoSuchItemRepError.new(rep_name)
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nanoc
4
+ module Core
5
+ class BasicItemRepView < ::Nanoc::Core::View
6
+ # @api private
7
+ def initialize(item_rep, context)
8
+ super(context)
9
+ @item_rep = item_rep
10
+ end
11
+
12
+ # @abstract
13
+ def item_view_class
14
+ Nanoc::Core::BasicItemView
15
+ end
16
+
17
+ # @api private
18
+ def _unwrap
19
+ @item_rep
20
+ end
21
+
22
+ # @see Object#==
23
+ def ==(other)
24
+ other.respond_to?(:item) && other.respond_to?(:name) && item == other.item && name == other.name
25
+ end
26
+
27
+ # @see Object#eql?
28
+ def eql?(other)
29
+ other.is_a?(self.class) &&
30
+ item.eql?(other.item) &&
31
+ name.eql?(other.name)
32
+ end
33
+
34
+ # @see Object#hash
35
+ def hash
36
+ self.class.hash ^ item.identifier.hash ^ name.hash
37
+ end
38
+
39
+ # @return [Symbol]
40
+ def name
41
+ @item_rep.name
42
+ end
43
+
44
+ def snapshot?(name)
45
+ @context.dependency_tracker.bounce(_unwrap.item, compiled_content: true)
46
+ @item_rep.snapshot?(name)
47
+ end
48
+
49
+ # Returns the item rep’s path, as used when being linked to. It starts
50
+ # with a slash and it is relative to the output directory. It does not
51
+ # include the path to the output directory. It will not include the
52
+ # filename if the filename is an index filename.
53
+ #
54
+ # @param [Symbol] snapshot The snapshot for which the path should be
55
+ # returned.
56
+ #
57
+ # @return [String] The item rep’s path.
58
+ def path(snapshot: :last)
59
+ @context.dependency_tracker.bounce(_unwrap.item, path: true)
60
+ @item_rep.path(snapshot: snapshot)
61
+ end
62
+
63
+ # Returns the item that this item rep belongs to.
64
+ #
65
+ # @return [Nanoc::Core::CompilationItemView]
66
+ def item
67
+ item_view_class.new(@item_rep.item, @context)
68
+ end
69
+
70
+ # @api private
71
+ def binary?
72
+ snapshot_def = _unwrap.snapshot_defs.find { |sd| sd.name == :last }
73
+ raise Nanoc::Core::Errors::NoSuchSnapshot.new(_unwrap, :last) if snapshot_def.nil?
74
+
75
+ snapshot_def.binary?
76
+ end
77
+
78
+ def inspect
79
+ "<#{self.class} item.identifier=#{item.identifier} name=#{name}>"
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nanoc
4
+ module Core
5
+ class BasicItemView < ::Nanoc::Core::View
6
+ include Nanoc::Core::DocumentViewMixin
7
+
8
+ # Returns the children of this item. For items with identifiers that have
9
+ # extensions, returns an empty collection.
10
+ #
11
+ # @return [Enumerable<Nanoc::Core::CompilationItemView>]
12
+ def children
13
+ unless _unwrap.identifier.legacy?
14
+ raise Nanoc::Core::Errors::CannotGetParentOrChildrenOfNonLegacyItem.new(_unwrap.identifier)
15
+ end
16
+
17
+ children_pattern = Nanoc::Core::Pattern.from(_unwrap.identifier.to_s + '*/')
18
+ children = @context.items.select { |i| children_pattern.match?(i.identifier) }
19
+
20
+ children.map { |i| self.class.new(i, @context) }.freeze
21
+ end
22
+
23
+ # Returns the parent of this item, if one exists. For items with identifiers
24
+ # that have extensions, returns nil.
25
+ #
26
+ # @return [Nanoc::Core::CompilationItemView] if the item has a parent
27
+ #
28
+ # @return [nil] if the item has no parent
29
+ def parent
30
+ unless _unwrap.identifier.legacy?
31
+ raise Nanoc::Core::Errors::CannotGetParentOrChildrenOfNonLegacyItem.new(_unwrap.identifier)
32
+ end
33
+
34
+ parent_identifier = '/' + _unwrap.identifier.components[0..-2].join('/') + '/'
35
+ parent_identifier = '/' if parent_identifier == '//'
36
+
37
+ parent = @context.items[parent_identifier]
38
+
39
+ parent && self.class.new(parent, @context)
40
+ end
41
+
42
+ # @return [Boolean] True if the item is binary, false otherwise
43
+ def binary?
44
+ _unwrap.content.binary?
45
+ end
46
+
47
+ # @return [String, nil] The path to the file containing the uncompiled content of this item.
48
+ def raw_filename
49
+ @context.dependency_tracker.bounce(_unwrap, raw_content: true)
50
+ _unwrap.content.filename
51
+ end
52
+ end
53
+ end
54
+ end
@@ -95,12 +95,14 @@ module Nanoc
95
95
  define_behavior(Nanoc::Core::BinaryContent, BinaryContentUpdateBehavior)
96
96
  define_behavior(Nanoc::Core::Configuration, HashUpdateBehavior)
97
97
  define_behavior(Nanoc::Core::Context, ContextUpdateBehavior)
98
+ define_behavior(Nanoc::Core::CodeSnippet, DataUpdateBehavior)
98
99
  define_behavior(Nanoc::Core::IdentifiableCollection, ArrayUpdateBehavior)
99
100
  define_behavior(Nanoc::Core::Identifier, ToSUpdateBehavior)
100
101
  define_behavior(Nanoc::Core::Item, DocumentUpdateBehavior)
101
102
  define_behavior(Nanoc::Core::ItemRep, ItemRepUpdateBehavior)
102
103
  define_behavior(Nanoc::Core::Layout, DocumentUpdateBehavior)
103
104
  define_behavior(Nanoc::Core::TextualContent, StringUpdateBehavior)
105
+ define_behavior(Nanoc::Core::View, UnwrapUpdateBehavior)
104
106
 
105
107
  @behaviors
106
108
  end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nanoc
4
+ module Core
5
+ class CompilationItemRepCollectionView < ::Nanoc::Core::BasicItemRepCollectionView
6
+ # @api private
7
+ def view_class
8
+ Nanoc::Core::CompilationItemRepView
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nanoc
4
+ module Core
5
+ class CompilationItemRepView < ::Nanoc::Core::BasicItemRepView
6
+ # @abstract
7
+ def item_view_class
8
+ Nanoc::Core::CompilationItemView
9
+ end
10
+
11
+ # Returns the item rep’s raw path. It includes the path to the output
12
+ # directory and the full filename.
13
+ #
14
+ # @param [Symbol] snapshot The snapshot for which the path should be
15
+ # returned.
16
+ #
17
+ # @return [String] The item rep’s raw path.
18
+ def raw_path(snapshot: :last)
19
+ @context.dependency_tracker.bounce(_unwrap.item, compiled_content: true)
20
+
21
+ res = @item_rep.raw_path(snapshot: snapshot)
22
+
23
+ unless @item_rep.compiled?
24
+ Fiber.yield(Nanoc::Core::Errors::UnmetDependency.new(@item_rep, snapshot))
25
+ end
26
+
27
+ # Wait for file to exist
28
+ if res
29
+ start = Time.now
30
+ sleep 0.05 until File.file?(res) || Time.now - start > 1.0
31
+ raise Nanoc::Core::Errors::InternalInconsistency, "File did not apear in time: #{res}" unless File.file?(res)
32
+ end
33
+
34
+ res
35
+ end
36
+
37
+ # Returns the compiled content.
38
+ #
39
+ # @param [String] snapshot The name of the snapshot from which to
40
+ # fetch the compiled content. By default, the returned compiled content
41
+ # will be the content compiled right before the first layout call (if
42
+ # any).
43
+ #
44
+ # @return [String] The content at the given snapshot.
45
+ def compiled_content(snapshot: nil)
46
+ @context.dependency_tracker.bounce(_unwrap.item, compiled_content: true)
47
+ @context.compiled_content_store.compiled_content(rep: _unwrap, snapshot: snapshot)
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nanoc
4
+ module Core
5
+ class CompilationItemView < ::Nanoc::Core::BasicItemView
6
+ # Returns the compiled content.
7
+ #
8
+ # @param [String] rep The name of the representation
9
+ # from which the compiled content should be fetched. By default, the
10
+ # compiled content will be fetched from the default representation.
11
+ #
12
+ # @param [String] snapshot The name of the snapshot from which to
13
+ # fetch the compiled content. By default, the returned compiled content
14
+ # will be the content compiled right before the first layout call (if
15
+ # any).
16
+ #
17
+ # @return [String] The content of the given rep at the given snapshot.
18
+ def compiled_content(rep: :default, snapshot: nil)
19
+ reps.fetch(rep).compiled_content(snapshot: snapshot)
20
+ end
21
+
22
+ # Returns the item path, as used when being linked to. It starts
23
+ # with a slash and it is relative to the output directory. It does not
24
+ # include the path to the output directory. It will not include the
25
+ # filename if the filename is an index filename.
26
+ #
27
+ # @param [String] rep The name of the representation
28
+ # from which the path should be fetched. By default, the path will be
29
+ # fetched from the default representation.
30
+ #
31
+ # @param [Symbol] snapshot The snapshot for which the
32
+ # path should be returned.
33
+ #
34
+ # @return [String] The item’s path.
35
+ def path(rep: :default, snapshot: :last)
36
+ reps.fetch(rep).path(snapshot: snapshot)
37
+ end
38
+
39
+ # Returns the representations of this item.
40
+ #
41
+ # @return [Nanoc::Core::BasicItemRepCollectionView]
42
+ def reps
43
+ Nanoc::Core::CompilationItemRepCollectionView.new(@context.reps[_unwrap], @context)
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nanoc
4
+ module Core
5
+ module CompilationPhases
6
+ class Abstract
7
+ include Nanoc::Core::ContractsSupport
8
+
9
+ def initialize(wrapped:)
10
+ @wrapped = wrapped
11
+ end
12
+
13
+ def start
14
+ @wrapped&.start
15
+ end
16
+
17
+ def stop
18
+ @wrapped&.stop
19
+ end
20
+
21
+ def call(rep, is_outdated:)
22
+ notify(:phase_started, rep)
23
+ run(rep, is_outdated: is_outdated) do
24
+ notify(:phase_yielded, rep)
25
+ @wrapped.call(rep, is_outdated: is_outdated)
26
+ notify(:phase_resumed, rep)
27
+ end
28
+ notify(:phase_ended, rep)
29
+ rescue
30
+ notify(:phase_aborted, rep)
31
+ raise
32
+ end
33
+
34
+ contract Nanoc::Core::ItemRep, C::KeywordArgs[is_outdated: C::Bool], C::Func[C::None => C::Any] => C::Any
35
+ def run(_rep, is_outdated:) # rubocop:disable Lint/UnusedMethodArgument
36
+ raise NotImplementedError
37
+ end
38
+
39
+ private
40
+
41
+ def notify(sym, rep)
42
+ name = self.class.to_s.sub(/^.*::/, '')
43
+ Nanoc::Core::NotificationCenter.post(sym, name, rep)
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end