nanoc3 3.2.4 → 3.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (211) hide show
  1. metadata +14 -313
  2. data/.gemtest +0 -0
  3. data/ChangeLog +0 -3
  4. data/Gemfile +0 -29
  5. data/LICENSE +0 -19
  6. data/NEWS.md +0 -449
  7. data/README.md +0 -108
  8. data/Rakefile +0 -14
  9. data/bin/nanoc3 +0 -12
  10. data/doc/yardoc_templates/default/layout/html/footer.erb +0 -10
  11. data/lib/nanoc3.rb +0 -28
  12. data/lib/nanoc3/base.rb +0 -49
  13. data/lib/nanoc3/base/compilation/checksum_store.rb +0 -57
  14. data/lib/nanoc3/base/compilation/compiled_content_cache.rb +0 -62
  15. data/lib/nanoc3/base/compilation/compiler.rb +0 -455
  16. data/lib/nanoc3/base/compilation/compiler_dsl.rb +0 -214
  17. data/lib/nanoc3/base/compilation/dependency_tracker.rb +0 -196
  18. data/lib/nanoc3/base/compilation/filter.rb +0 -165
  19. data/lib/nanoc3/base/compilation/item_rep_proxy.rb +0 -102
  20. data/lib/nanoc3/base/compilation/item_rep_recorder_proxy.rb +0 -88
  21. data/lib/nanoc3/base/compilation/outdatedness_checker.rb +0 -223
  22. data/lib/nanoc3/base/compilation/outdatedness_reasons.rb +0 -46
  23. data/lib/nanoc3/base/compilation/rule.rb +0 -73
  24. data/lib/nanoc3/base/compilation/rule_context.rb +0 -84
  25. data/lib/nanoc3/base/compilation/rule_memory_calculator.rb +0 -40
  26. data/lib/nanoc3/base/compilation/rule_memory_store.rb +0 -53
  27. data/lib/nanoc3/base/compilation/rules_collection.rb +0 -231
  28. data/lib/nanoc3/base/context.rb +0 -47
  29. data/lib/nanoc3/base/core_ext.rb +0 -6
  30. data/lib/nanoc3/base/core_ext/array.rb +0 -62
  31. data/lib/nanoc3/base/core_ext/hash.rb +0 -63
  32. data/lib/nanoc3/base/core_ext/pathname.rb +0 -26
  33. data/lib/nanoc3/base/core_ext/string.rb +0 -46
  34. data/lib/nanoc3/base/directed_graph.rb +0 -275
  35. data/lib/nanoc3/base/errors.rb +0 -174
  36. data/lib/nanoc3/base/memoization.rb +0 -67
  37. data/lib/nanoc3/base/notification_center.rb +0 -84
  38. data/lib/nanoc3/base/ordered_hash.rb +0 -200
  39. data/lib/nanoc3/base/plugin_registry.rb +0 -165
  40. data/lib/nanoc3/base/result_data/item_rep.rb +0 -488
  41. data/lib/nanoc3/base/source_data/code_snippet.rb +0 -58
  42. data/lib/nanoc3/base/source_data/configuration.rb +0 -24
  43. data/lib/nanoc3/base/source_data/data_source.rb +0 -234
  44. data/lib/nanoc3/base/source_data/item.rb +0 -301
  45. data/lib/nanoc3/base/source_data/layout.rb +0 -130
  46. data/lib/nanoc3/base/source_data/site.rb +0 -361
  47. data/lib/nanoc3/base/store.rb +0 -135
  48. data/lib/nanoc3/cli.rb +0 -133
  49. data/lib/nanoc3/cli/command.rb +0 -139
  50. data/lib/nanoc3/cli/commands/autocompile.rb +0 -60
  51. data/lib/nanoc3/cli/commands/compile.rb +0 -280
  52. data/lib/nanoc3/cli/commands/create_item.rb +0 -62
  53. data/lib/nanoc3/cli/commands/create_layout.rb +0 -75
  54. data/lib/nanoc3/cli/commands/create_site.rb +0 -410
  55. data/lib/nanoc3/cli/commands/debug.rb +0 -119
  56. data/lib/nanoc3/cli/commands/info.rb +0 -98
  57. data/lib/nanoc3/cli/commands/nanoc.rb +0 -37
  58. data/lib/nanoc3/cli/commands/update.rb +0 -72
  59. data/lib/nanoc3/cli/commands/view.rb +0 -84
  60. data/lib/nanoc3/cli/commands/watch.rb +0 -125
  61. data/lib/nanoc3/cli/error_handler.rb +0 -193
  62. data/lib/nanoc3/cli/logger.rb +0 -91
  63. data/lib/nanoc3/data_sources.rb +0 -29
  64. data/lib/nanoc3/data_sources/deprecated/delicious.rb +0 -42
  65. data/lib/nanoc3/data_sources/deprecated/last_fm.rb +0 -87
  66. data/lib/nanoc3/data_sources/deprecated/twitter.rb +0 -38
  67. data/lib/nanoc3/data_sources/filesystem.rb +0 -299
  68. data/lib/nanoc3/data_sources/filesystem_unified.rb +0 -116
  69. data/lib/nanoc3/data_sources/filesystem_verbose.rb +0 -86
  70. data/lib/nanoc3/extra.rb +0 -22
  71. data/lib/nanoc3/extra/auto_compiler.rb +0 -103
  72. data/lib/nanoc3/extra/chick.rb +0 -125
  73. data/lib/nanoc3/extra/core_ext.rb +0 -4
  74. data/lib/nanoc3/extra/core_ext/enumerable.rb +0 -33
  75. data/lib/nanoc3/extra/core_ext/time.rb +0 -19
  76. data/lib/nanoc3/extra/deployers.rb +0 -11
  77. data/lib/nanoc3/extra/deployers/rsync.rb +0 -114
  78. data/lib/nanoc3/extra/file_proxy.rb +0 -40
  79. data/lib/nanoc3/extra/validators.rb +0 -12
  80. data/lib/nanoc3/extra/validators/links.rb +0 -264
  81. data/lib/nanoc3/extra/validators/w3c.rb +0 -95
  82. data/lib/nanoc3/extra/vcs.rb +0 -66
  83. data/lib/nanoc3/extra/vcses.rb +0 -17
  84. data/lib/nanoc3/extra/vcses/bazaar.rb +0 -25
  85. data/lib/nanoc3/extra/vcses/dummy.rb +0 -24
  86. data/lib/nanoc3/extra/vcses/git.rb +0 -25
  87. data/lib/nanoc3/extra/vcses/mercurial.rb +0 -25
  88. data/lib/nanoc3/extra/vcses/subversion.rb +0 -25
  89. data/lib/nanoc3/filters.rb +0 -53
  90. data/lib/nanoc3/filters/asciidoc.rb +0 -38
  91. data/lib/nanoc3/filters/bluecloth.rb +0 -19
  92. data/lib/nanoc3/filters/coderay.rb +0 -21
  93. data/lib/nanoc3/filters/colorize_syntax.rb +0 -261
  94. data/lib/nanoc3/filters/erb.rb +0 -35
  95. data/lib/nanoc3/filters/erubis.rb +0 -27
  96. data/lib/nanoc3/filters/haml.rb +0 -27
  97. data/lib/nanoc3/filters/kramdown.rb +0 -20
  98. data/lib/nanoc3/filters/less.rb +0 -53
  99. data/lib/nanoc3/filters/markaby.rb +0 -20
  100. data/lib/nanoc3/filters/maruku.rb +0 -20
  101. data/lib/nanoc3/filters/mustache.rb +0 -24
  102. data/lib/nanoc3/filters/rainpress.rb +0 -19
  103. data/lib/nanoc3/filters/rdiscount.rb +0 -22
  104. data/lib/nanoc3/filters/rdoc.rb +0 -33
  105. data/lib/nanoc3/filters/redcarpet.rb +0 -27
  106. data/lib/nanoc3/filters/redcloth.rb +0 -47
  107. data/lib/nanoc3/filters/relativize_paths.rb +0 -45
  108. data/lib/nanoc3/filters/rubypants.rb +0 -20
  109. data/lib/nanoc3/filters/sass.rb +0 -66
  110. data/lib/nanoc3/filters/slim.rb +0 -25
  111. data/lib/nanoc3/filters/typogruby.rb +0 -23
  112. data/lib/nanoc3/filters/uglify_js.rb +0 -42
  113. data/lib/nanoc3/helpers.rb +0 -16
  114. data/lib/nanoc3/helpers/blogging.rb +0 -319
  115. data/lib/nanoc3/helpers/breadcrumbs.rb +0 -40
  116. data/lib/nanoc3/helpers/capturing.rb +0 -138
  117. data/lib/nanoc3/helpers/filtering.rb +0 -50
  118. data/lib/nanoc3/helpers/html_escape.rb +0 -55
  119. data/lib/nanoc3/helpers/link_to.rb +0 -151
  120. data/lib/nanoc3/helpers/rendering.rb +0 -140
  121. data/lib/nanoc3/helpers/tagging.rb +0 -71
  122. data/lib/nanoc3/helpers/text.rb +0 -44
  123. data/lib/nanoc3/helpers/xml_sitemap.rb +0 -76
  124. data/lib/nanoc3/tasks.rb +0 -10
  125. data/lib/nanoc3/tasks/clean.rake +0 -16
  126. data/lib/nanoc3/tasks/clean.rb +0 -29
  127. data/lib/nanoc3/tasks/deploy/rsync.rake +0 -14
  128. data/lib/nanoc3/tasks/validate.rake +0 -92
  129. data/nanoc3.gemspec +0 -49
  130. data/tasks/doc.rake +0 -16
  131. data/tasks/test.rake +0 -44
  132. data/test/base/core_ext/array_spec.rb +0 -73
  133. data/test/base/core_ext/hash_spec.rb +0 -98
  134. data/test/base/core_ext/pathname_spec.rb +0 -27
  135. data/test/base/core_ext/string_spec.rb +0 -37
  136. data/test/base/test_checksum_store.rb +0 -35
  137. data/test/base/test_code_snippet.rb +0 -31
  138. data/test/base/test_compiler.rb +0 -316
  139. data/test/base/test_compiler_dsl.rb +0 -161
  140. data/test/base/test_context.rb +0 -31
  141. data/test/base/test_data_source.rb +0 -46
  142. data/test/base/test_dependency_tracker.rb +0 -262
  143. data/test/base/test_directed_graph.rb +0 -283
  144. data/test/base/test_filter.rb +0 -83
  145. data/test/base/test_item.rb +0 -179
  146. data/test/base/test_item_rep.rb +0 -553
  147. data/test/base/test_layout.rb +0 -59
  148. data/test/base/test_memoization.rb +0 -90
  149. data/test/base/test_notification_center.rb +0 -34
  150. data/test/base/test_outdatedness_checker.rb +0 -394
  151. data/test/base/test_plugin.rb +0 -30
  152. data/test/base/test_rule.rb +0 -19
  153. data/test/base/test_rule_context.rb +0 -65
  154. data/test/base/test_site.rb +0 -190
  155. data/test/cli/commands/test_compile.rb +0 -33
  156. data/test/cli/commands/test_create_item.rb +0 -14
  157. data/test/cli/commands/test_create_layout.rb +0 -28
  158. data/test/cli/commands/test_create_site.rb +0 -24
  159. data/test/cli/commands/test_help.rb +0 -12
  160. data/test/cli/commands/test_info.rb +0 -11
  161. data/test/cli/commands/test_update.rb +0 -10
  162. data/test/cli/test_cli.rb +0 -102
  163. data/test/cli/test_error_handler.rb +0 -29
  164. data/test/cli/test_logger.rb +0 -10
  165. data/test/data_sources/test_filesystem.rb +0 -433
  166. data/test/data_sources/test_filesystem_unified.rb +0 -536
  167. data/test/data_sources/test_filesystem_verbose.rb +0 -357
  168. data/test/extra/core_ext/test_enumerable.rb +0 -30
  169. data/test/extra/core_ext/test_time.rb +0 -15
  170. data/test/extra/deployers/test_rsync.rb +0 -232
  171. data/test/extra/test_auto_compiler.rb +0 -417
  172. data/test/extra/test_file_proxy.rb +0 -19
  173. data/test/extra/test_vcs.rb +0 -22
  174. data/test/extra/validators/test_links.rb +0 -51
  175. data/test/extra/validators/test_w3c.rb +0 -47
  176. data/test/filters/test_asciidoc.rb +0 -22
  177. data/test/filters/test_bluecloth.rb +0 -18
  178. data/test/filters/test_coderay.rb +0 -44
  179. data/test/filters/test_colorize_syntax.rb +0 -283
  180. data/test/filters/test_erb.rb +0 -99
  181. data/test/filters/test_erubis.rb +0 -70
  182. data/test/filters/test_haml.rb +0 -96
  183. data/test/filters/test_kramdown.rb +0 -18
  184. data/test/filters/test_less.rb +0 -113
  185. data/test/filters/test_markaby.rb +0 -24
  186. data/test/filters/test_maruku.rb +0 -18
  187. data/test/filters/test_mustache.rb +0 -25
  188. data/test/filters/test_rainpress.rb +0 -29
  189. data/test/filters/test_rdiscount.rb +0 -31
  190. data/test/filters/test_rdoc.rb +0 -18
  191. data/test/filters/test_redcarpet.rb +0 -63
  192. data/test/filters/test_redcloth.rb +0 -33
  193. data/test/filters/test_relativize_paths.rb +0 -332
  194. data/test/filters/test_rubypants.rb +0 -18
  195. data/test/filters/test_sass.rb +0 -229
  196. data/test/filters/test_slim.rb +0 -35
  197. data/test/filters/test_typogruby.rb +0 -21
  198. data/test/filters/test_uglify_js.rb +0 -30
  199. data/test/gem_loader.rb +0 -11
  200. data/test/helper.rb +0 -179
  201. data/test/helpers/test_blogging.rb +0 -754
  202. data/test/helpers/test_breadcrumbs.rb +0 -81
  203. data/test/helpers/test_capturing.rb +0 -41
  204. data/test/helpers/test_filtering.rb +0 -106
  205. data/test/helpers/test_html_escape.rb +0 -32
  206. data/test/helpers/test_link_to.rb +0 -249
  207. data/test/helpers/test_rendering.rb +0 -89
  208. data/test/helpers/test_tagging.rb +0 -87
  209. data/test/helpers/test_text.rb +0 -24
  210. data/test/helpers/test_xml_sitemap.rb +0 -103
  211. data/test/tasks/test_clean.rb +0 -67
@@ -1,47 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Nanoc3
4
-
5
- # Provides a context and a binding for use in filters such as the ERB and
6
- # Haml ones.
7
- class Context
8
-
9
- # Creates a new context based off the contents of the hash.
10
- #
11
- # Each pair in the hash will be converted to an instance variable and an
12
- # instance method. For example, passing the hash `{ :foo => 'bar' }` will
13
- # cause `@foo` to have the value `"bar"`, and the instance method `#foo`
14
- # to return the same value `"bar"`.
15
- #
16
- # @param [Hash] hash A list of key-value pairs to make available
17
- #
18
- # @example Defining a context and accessing values
19
- #
20
- # context = Nanoc3::Context.new(
21
- # :name => 'Max Payne',
22
- # :location => 'in a cheap motel'
23
- # )
24
- # context.instance_eval do
25
- # "I am #{name} and I am hiding #{@location}."
26
- # end
27
- # # => "I am Max Payne and I am hiding in a cheap motel."
28
- def initialize(hash)
29
- hash.each_pair do |key, value|
30
- # Build instance variable
31
- instance_variable_set('@' + key.to_s, value)
32
-
33
- # Define method
34
- metaclass = (class << self ; self ; end)
35
- metaclass.send(:define_method, key) { value }
36
- end
37
- end
38
-
39
- # Returns a binding for this instance.
40
- #
41
- # @return [Binding] A binding for this instance
42
- def get_binding
43
- binding
44
- end
45
-
46
- end
47
- end
@@ -1,6 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require 'nanoc3/base/core_ext/array'
4
- require 'nanoc3/base/core_ext/hash'
5
- require 'nanoc3/base/core_ext/pathname'
6
- require 'nanoc3/base/core_ext/string'
@@ -1,62 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Nanoc3::ArrayExtensions
4
-
5
- # Returns a new array where all items' keys are recursively converted to
6
- # symbols by calling {Nanoc3::ArrayExtensions#symbolize_keys} or
7
- # {Nanoc3::HashExtensions#symbolize_keys}.
8
- #
9
- # @return [Array] The converted array
10
- def symbolize_keys
11
- inject([]) do |array, element|
12
- array + [ element.respond_to?(:symbolize_keys) ? element.symbolize_keys : element ]
13
- end
14
- end
15
-
16
- # Returns a new array where all items' keys are recursively converted to
17
- # strings by calling {Nanoc3::ArrayExtensions#stringify_keys} or
18
- # {Nanoc3::HashExtensions#stringify_keys}.
19
- #
20
- # @return [Array] The converted array
21
- def stringify_keys
22
- inject([]) do |array, element|
23
- array + [ element.respond_to?(:stringify_keys) ? element.stringify_keys : element ]
24
- end
25
- end
26
-
27
- # Freezes the contents of the array, as well as all array elements. The
28
- # array elements will be frozen using {#freeze_recursively} if they respond
29
- # to that message, or #freeze if they do not.
30
- #
31
- # @see Hash#freeze_recursively
32
- #
33
- # @return [void]
34
- #
35
- # @since 3.2.0
36
- def freeze_recursively
37
- return if self.frozen?
38
- freeze
39
- each do |value|
40
- if value.respond_to?(:freeze_recursively)
41
- value.freeze_recursively
42
- else
43
- value.freeze
44
- end
45
- end
46
- end
47
-
48
- # Calculates the checksum for this array. Any change to this array will
49
- # result in a different checksum.
50
- #
51
- # @return [String] The checksum for this array
52
- #
53
- # @api private
54
- def checksum
55
- Marshal.dump(self).checksum
56
- end
57
-
58
- end
59
-
60
- class Array
61
- include Nanoc3::ArrayExtensions
62
- end
@@ -1,63 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Nanoc3::HashExtensions
4
-
5
- # Returns a new hash where all keys are recursively converted to symbols by
6
- # calling {Nanoc3::ArrayExtensions#symbolize_keys} or
7
- # {Nanoc3::HashExtensions#symbolize_keys}.
8
- #
9
- # @return [Hash] The converted hash
10
- def symbolize_keys
11
- inject({}) do |hash, (key, value)|
12
- hash.merge(key.to_sym => value.respond_to?(:symbolize_keys) ? value.symbolize_keys : value)
13
- end
14
- end
15
-
16
- # Returns a new hash where all keys are recursively converted to strings by
17
- # calling {Nanoc3::ArrayExtensions#stringify_keys} or
18
- # {Nanoc3::HashExtensions#stringify_keys}.
19
- #
20
- # @return [Hash] The converted hash
21
- def stringify_keys
22
- inject({}) do |hash, (key, value)|
23
- hash.merge(key.to_s => value.respond_to?(:stringify_keys) ? value.stringify_keys : value)
24
- end
25
- end
26
-
27
- # Freezes the contents of the hash, as well as all hash values. The hash
28
- # values will be frozen using {#freeze_recursively} if they respond to
29
- # that message, or #freeze if they do not.
30
- #
31
- # @see Array#freeze_recursively
32
- #
33
- # @return [void]
34
- #
35
- # @since 3.2.0
36
- def freeze_recursively
37
- return if self.frozen?
38
- freeze
39
- each_pair do |key, value|
40
- if value.respond_to?(:freeze_recursively)
41
- value.freeze_recursively
42
- else
43
- value.freeze
44
- end
45
- end
46
- end
47
-
48
- # Calculates the checksum for this hash. Any change to this hash will result
49
- # in a different checksum.
50
- #
51
- # @return [String] The checksum for this hash
52
- #
53
- # @api private
54
- def checksum
55
- array = self.to_a.sort_by { |kv| kv[0].to_s }
56
- array.checksum
57
- end
58
-
59
- end
60
-
61
- class Hash
62
- include Nanoc3::HashExtensions
63
- end
@@ -1,26 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Nanoc3::PathnameExtensions
4
-
5
- # Calculates the checksum for the file referenced to by this pathname. Any
6
- # change to the file contents will result in a different checksum.
7
- #
8
- # @return [String] The checksum for this file
9
- #
10
- # @api private
11
- def checksum
12
- digest = Digest::SHA1.new
13
- File.open(self.to_s, 'r') do |io|
14
- until io.eof
15
- data = io.read(2**10)
16
- digest.update(data)
17
- end
18
- end
19
- digest.hexdigest
20
- end
21
-
22
- end
23
-
24
- class Pathname
25
- include Nanoc3::PathnameExtensions
26
- end
@@ -1,46 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Nanoc3::StringExtensions
4
-
5
- # Transforms string into an actual identifier
6
- #
7
- # @return [String] The identifier generated from the receiver
8
- def cleaned_identifier
9
- "/#{self}/".gsub(/^\/+|\/+$/, '/')
10
- end
11
-
12
- # Replaces Unicode characters with their ASCII decompositions if the
13
- # environment does not support Unicode.
14
- #
15
- # This method is not suited for general usage. If you need similar
16
- # functionality, consider using the Iconv library instead.
17
- #
18
- # @return [String] The decomposed string
19
- def make_compatible_with_env
20
- # Check whether environment supports Unicode
21
- # FIXME this is ugly, and there most likely are better ways to do this
22
- is_unicode_supported = %w( LC_ALL LC_CTYPE LANG ).any? { |e| ENV[e] =~ /UTF/ }
23
- return self if is_unicode_supported
24
-
25
- # Decompose if necessary
26
- # FIXME this decomposition is not generally usable
27
- self.gsub(/“|”/, '"').gsub(/‘|’/, '\'').gsub('…', '...')
28
- end
29
-
30
- # Calculates the checksum for this string. Any change to this string will
31
- # result in a different checksum.
32
- #
33
- # @return [String] The checksum for this string
34
- #
35
- # @api private
36
- def checksum
37
- digest = Digest::SHA1.new
38
- digest.update(self)
39
- digest.hexdigest
40
- end
41
-
42
- end
43
-
44
- class String
45
- include Nanoc3::StringExtensions
46
- end
@@ -1,275 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Nanoc3
4
-
5
- # Represents a directed graph. It is used by the dependency tracker for
6
- # storing and querying dependencies between items.
7
- #
8
- # @example Creating and using a directed graph
9
- #
10
- # # Create a graph with three vertices
11
- # graph = DirectedGraph.new(%w( a b c d ))
12
- #
13
- # # Add edges
14
- # graph.add_edge('a', 'b')
15
- # graph.add_edge('b', 'c')
16
- # graph.add_edge('c', 'd')
17
- #
18
- # # Get (direct) predecessors
19
- # graph.direct_predecessors_of('d').sort
20
- # # => %w( c )
21
- # graph.predecessors_of('d').sort
22
- # # => %w( a b c )
23
- #
24
- # # Modify edges
25
- # graph.delete_edge('a', 'b')
26
- #
27
- # # Get (direct) predecessors again
28
- # graph.direct_predecessors_of('d').sort
29
- # # => %w( c )
30
- # graph.predecessors_of('d').sort
31
- # # => %w( b c )
32
- class DirectedGraph
33
-
34
- # The set of vertices in this graph.
35
- #
36
- # @return [Set]
37
- attr_reader :vertices
38
-
39
- # @group Creating a graph
40
-
41
- # Creates a new directed graph with the given vertices.
42
- def initialize(vertices)
43
- @vertices = Set.new(vertices)
44
-
45
- @from_graph = {}
46
- @to_graph = {}
47
-
48
- @vertice_indexes = {}
49
- @vertices.each_with_index do |v, i|
50
- @vertice_indexes[v] = i
51
- end
52
-
53
- @roots = Set.new(@vertices)
54
-
55
- invalidate_caches
56
- end
57
-
58
- # @group Modifying the graph
59
-
60
- # Adds an edge from the first vertex to the second vertex.
61
- #
62
- # @param from Vertex where the edge should start
63
- #
64
- # @param to Vertex where the edge should end
65
- #
66
- # @return [void]
67
- def add_edge(from, to)
68
- add_vertex(from)
69
- add_vertex(to)
70
-
71
- @from_graph[from] ||= Set.new
72
- @from_graph[from] << to
73
-
74
- @to_graph[to] ||= Set.new
75
- @to_graph[to] << from
76
-
77
- @roots.delete(to)
78
-
79
- invalidate_caches
80
- end
81
-
82
- # Removes the edge from the first vertex to the second vertex. If the
83
- # edge does not exist, nothing is done.
84
- #
85
- # @param from Start vertex of the edge
86
- #
87
- # @param to End vertex of the edge
88
- #
89
- # @return [void]
90
- #
91
- # @since 3.2.0
92
- def delete_edge(from, to)
93
- @from_graph[from] ||= Set.new
94
- @from_graph[from].delete(to)
95
-
96
- @to_graph[to] ||= Set.new
97
- @to_graph[to].delete(from)
98
-
99
- @roots.add(to) if @to_graph[to].empty?
100
-
101
- invalidate_caches
102
- end
103
-
104
- # Adds the given vertex to the graph.
105
- #
106
- # @param v The vertex to add to the graph
107
- #
108
- # @return [void]
109
- #
110
- # @since 3.2.0
111
- def add_vertex(v)
112
- return if @vertices.include?(v)
113
-
114
- @vertices << v
115
- @vertice_indexes[v] = @vertices.size-1
116
-
117
- @roots << v
118
- end
119
-
120
- # Deletes all edges coming from the given vertex.
121
- #
122
- # @param from Vertex from which all edges should be removed
123
- #
124
- # @return [void]
125
- #
126
- # @since 3.2.0
127
- def delete_edges_from(from)
128
- return if @from_graph[from].nil?
129
-
130
- @from_graph[from].each do |to|
131
- @to_graph[to].delete(from)
132
- @roots.add(to) if @to_graph[to].empty?
133
- end
134
- @from_graph.delete(from)
135
- end
136
-
137
- # Deletes all edges going to the given vertex.
138
- #
139
- # @param to Vertex to which all edges should be removed
140
- #
141
- # @return [void]
142
- def delete_edges_to(to)
143
- return if @to_graph[to].nil?
144
-
145
- @to_graph[to].each do |from|
146
- @from_graph[from].delete(to)
147
- end
148
- @to_graph.delete(to)
149
- @roots.add(to)
150
- end
151
-
152
- # Removes the given vertex from the graph.
153
- #
154
- # @param v Vertex to remove from the graph
155
- #
156
- # @return [void]
157
- #
158
- # @since 3.2.0
159
- def delete_vertex(v)
160
- delete_edges_to(v)
161
- delete_edges_from(v)
162
-
163
- @vertices.delete(v)
164
- @roots.delete(v)
165
- end
166
-
167
- # @group Querying the graph
168
-
169
- # Returns the direct predecessors of the given vertex, i.e. the vertices
170
- # x where there is an edge from x to the given vertex y.
171
- #
172
- # @param to The vertex of which the predecessors should be calculated
173
- #
174
- # @return [Array] Direct predecessors of the given vertex
175
- def direct_predecessors_of(to)
176
- @to_graph[to].to_a
177
- end
178
-
179
- # Returns the direct successors of the given vertex, i.e. the vertices y
180
- # where there is an edge from the given vertex x to y.
181
- #
182
- # @param from The vertex of which the successors should be calculated
183
- #
184
- # @return [Array] Direct successors of the given vertex
185
- def direct_successors_of(from)
186
- @from_graph[from].to_a
187
- end
188
-
189
- # Returns the predecessors of the given vertex, i.e. the vertices x for
190
- # which there is a path from x to the given vertex y.
191
- #
192
- # @param to The vertex of which the predecessors should be calculated
193
- #
194
- # @return [Array] Predecessors of the given vertex
195
- def predecessors_of(to)
196
- @predecessors[to] ||= recursively_find_vertices(to, :direct_predecessors_of)
197
- end
198
-
199
- # Returns the successors of the given vertex, i.e. the vertices y for
200
- # which there is a path from the given vertex x to y.
201
- #
202
- # @param from The vertex of which the successors should be calculated
203
- #
204
- # @return [Array] Successors of the given vertex
205
- def successors_of(from)
206
- @successors[from] ||= recursively_find_vertices(from, :direct_successors_of)
207
- end
208
-
209
- # Returns an array of tuples representing the edges. The result of this
210
- # method may take a while to compute and should be cached if possible.
211
- #
212
- # @return [Array] The list of all edges in this graph.
213
- def edges
214
- result = []
215
- @vertices.each_with_index do |v, i|
216
- direct_successors_of(v).map { |v2| @vertice_indexes[v2] }.each do |i2|
217
- result << [ i, i2 ]
218
- end
219
- end
220
- result
221
- end
222
-
223
- # Returns all root vertices, i.e. vertices where no edge points to.
224
- #
225
- # @return [Set] The set of all root vertices in this graph.
226
- #
227
- # @since 3.2.0
228
- def roots
229
- @roots
230
- end
231
-
232
- # @group Deprecated methods
233
-
234
- # @deprecated Use {#delete_edge} instead
235
- def remove_edge(from, to)
236
- delete_edge(from, to)
237
- end
238
-
239
- private
240
-
241
- # Invalidates cached data. This method should be called when the internal
242
- # graph representation is changed.
243
- def invalidate_caches
244
- @predecessors = {}
245
- @successors = {}
246
- end
247
-
248
- # Recursively finds vertices, starting at the vertex start, using the
249
- # given method, which should be a symbol to a method that takes a vertex
250
- # and returns related vertices (e.g. predecessors, successors).
251
- def recursively_find_vertices(start, method)
252
- all_vertices = Set.new
253
-
254
- processed_vertices = Set.new
255
- unprocessed_vertices = [ start ]
256
-
257
- until unprocessed_vertices.empty?
258
- # Get next unprocessed vertex
259
- vertex = unprocessed_vertices.pop
260
- next if processed_vertices.include?(vertex)
261
- processed_vertices << vertex
262
-
263
- # Add predecessors of this vertex
264
- send(method, vertex).each do |v|
265
- all_vertices << v unless all_vertices.include?(v)
266
- unprocessed_vertices << v
267
- end
268
- end
269
-
270
- all_vertices.to_a
271
- end
272
-
273
- end
274
-
275
- end