middleman-core 4.0.0.alpha.2 → 4.0.0.alpha.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/features/asset_hash.feature +26 -8
  3. data/features/chained_templates.feature +88 -1
  4. data/features/cli_init.feature +0 -18
  5. data/features/collections.feature +145 -0
  6. data/features/console.feature +11 -0
  7. data/features/front-matter.feature +11 -0
  8. data/features/paginate.feature +204 -0
  9. data/features/partials.feature +0 -5
  10. data/features/slim.feature +1 -1
  11. data/features/working_directory.feature +33 -0
  12. data/fixtures/asset-hash-app/source/api.json.erb +1 -0
  13. data/fixtures/asset-hash-app/source/images/200px.jpg +0 -0
  14. data/fixtures/asset-hash-app/source/images/300px.jpg +0 -0
  15. data/fixtures/asset-hash-app/source/index.html.erb +1 -1
  16. data/fixtures/asset-hash-app/source/subdir/api.json.erb +1 -0
  17. data/fixtures/collections-app/config.rb +16 -0
  18. data/fixtures/collections-app/source/blog1/2011-01-01-new-article.html.markdown +7 -0
  19. data/fixtures/collections-app/source/blog1/2011-01-02-another-article.html.markdown +9 -0
  20. data/fixtures/collections-app/source/blog2/2011-01-01-new-article.html.markdown +7 -0
  21. data/fixtures/collections-app/source/blog2/2011-01-02-another-article.html.markdown +8 -0
  22. data/fixtures/collections-app/source/index.html.erb +26 -0
  23. data/fixtures/frontmatter-app/source/front-matter-pandoc.html.md.erb +13 -0
  24. data/fixtures/generator-test/config.rb +2 -7
  25. data/fixtures/multiple-data-sources-app/source/index.html.erb +0 -5
  26. data/fixtures/{more-instance-vars-app → paginate-app}/config.rb +0 -0
  27. data/fixtures/paginate-app/source/archive/2011/index.html.erb +20 -0
  28. data/fixtures/paginate-app/source/blog/2011-01-01-test-article.html.markdown +6 -0
  29. data/fixtures/paginate-app/source/blog/2011-01-02-test-article.html.markdown +6 -0
  30. data/fixtures/paginate-app/source/blog/2011-01-03-test-article.html.markdown +6 -0
  31. data/fixtures/paginate-app/source/blog/2011-01-04-test-article.html.markdown +6 -0
  32. data/fixtures/paginate-app/source/blog/2011-01-05-test-article.html.markdown +6 -0
  33. data/fixtures/paginate-app/source/blog/2011-02-01-test-article.html.markdown +6 -0
  34. data/fixtures/paginate-app/source/blog/2011-02-02-test-article.html.markdown +6 -0
  35. data/fixtures/paginate-app/source/index.html.erb +15 -0
  36. data/fixtures/paginate-app/source/tag.html.erb +23 -0
  37. data/fixtures/partial-chained_templates-app/config.rb +0 -0
  38. data/lib/middleman-core/application.rb +28 -1
  39. data/lib/middleman-core/builder.rb +2 -0
  40. data/lib/middleman-core/contracts.rb +19 -1
  41. data/lib/middleman-core/core_extensions.rb +5 -0
  42. data/lib/middleman-core/core_extensions/collections.rb +82 -0
  43. data/lib/middleman-core/core_extensions/collections/lazy_root.rb +30 -0
  44. data/lib/middleman-core/core_extensions/collections/lazy_step.rb +48 -0
  45. data/lib/middleman-core/core_extensions/collections/pagination.rb +59 -0
  46. data/lib/middleman-core/core_extensions/collections/step_context.rb +26 -0
  47. data/lib/middleman-core/core_extensions/data.rb +1 -1
  48. data/lib/middleman-core/core_extensions/default_helpers.rb +1 -2
  49. data/lib/middleman-core/core_extensions/front_matter.rb +10 -3
  50. data/lib/middleman-core/core_extensions/i18n.rb +6 -7
  51. data/lib/middleman-core/core_extensions/show_exceptions.rb +1 -1
  52. data/lib/middleman-core/extension.rb +1 -1
  53. data/lib/middleman-core/extensions/automatic_image_sizes.rb +0 -2
  54. data/lib/middleman-core/file_renderer.rb +3 -1
  55. data/lib/middleman-core/load_paths.rb +2 -1
  56. data/lib/middleman-core/logger.rb +1 -1
  57. data/lib/middleman-core/meta_pages/sitemap_resource.rb +1 -1
  58. data/lib/middleman-core/preview_server.rb +1 -1
  59. data/lib/middleman-core/renderers/sass.rb +1 -1
  60. data/lib/middleman-core/renderers/slim.rb +2 -2
  61. data/lib/middleman-core/sitemap/extensions/on_disk.rb +1 -1
  62. data/lib/middleman-core/sitemap/extensions/proxies.rb +36 -50
  63. data/lib/middleman-core/sitemap/resource.rb +42 -3
  64. data/lib/middleman-core/sitemap/store.rb +5 -0
  65. data/lib/middleman-core/sources.rb +64 -24
  66. data/lib/middleman-core/sources/source_watcher.rb +47 -23
  67. data/lib/middleman-core/step_definitions/server_steps.rb +52 -21
  68. data/lib/middleman-core/template_context.rb +26 -5
  69. data/lib/middleman-core/template_renderer.rb +50 -33
  70. data/lib/middleman-core/util.rb +94 -1
  71. data/lib/middleman-core/util/hash_with_indifferent_access.rb +1 -1
  72. data/lib/middleman-core/version.rb +1 -1
  73. data/middleman-core.gemspec +2 -0
  74. metadata +90 -15
  75. data/features/more-instance_vars.feature +0 -18
  76. data/fixtures/more-instance-vars-app/source/_vartial.erb +0 -5
  77. data/fixtures/more-instance-vars-app/source/instance-var-set.html.erb +0 -2
  78. data/fixtures/more-instance-vars-app/source/layout.erb +0 -3
  79. data/fixtures/more-instance-vars-app/source/no-instance-var.html.erb +0 -1
@@ -52,6 +52,11 @@ Middleman::Extensions.register :routing, auto_activate: :before_configuration do
52
52
  Middleman::CoreExtensions::Routing
53
53
  end
54
54
 
55
+ Middleman::Extensions.register :collections, auto_activate: :before_configuration do
56
+ require 'middleman-core/core_extensions/collections'
57
+ Middleman::CoreExtensions::Collections::CollectionsExtension
58
+ end
59
+
55
60
  ###
56
61
  # Setup Optional Extensions
57
62
  ###
@@ -0,0 +1,82 @@
1
+ require 'middleman-core/core_extensions/collections/pagination'
2
+ require 'middleman-core/core_extensions/collections/step_context'
3
+ require 'middleman-core/core_extensions/collections/lazy_root'
4
+ require 'middleman-core/core_extensions/collections/lazy_step'
5
+
6
+ # Super "class-y" injection of array helpers
7
+ class Array
8
+ include Middleman::Pagination::ArrayHelpers
9
+ end
10
+
11
+ module Middleman
12
+ module CoreExtensions
13
+ module Collections
14
+ class CollectionsExtension < Extension
15
+ # This should run after most other sitemap manipulators so that it
16
+ # gets a chance to modify any new resources that get added.
17
+ self.resource_list_manipulator_priority = 110
18
+
19
+ attr_accessor :root_collector, :leaves
20
+
21
+ def initialize(app, options_hash={}, &block)
22
+ super
23
+
24
+ @leaves = Set.new
25
+ @collectors_by_name = {}
26
+ @values_by_name = {}
27
+
28
+ @root_collector = LazyCollectorRoot.new(self)
29
+ end
30
+
31
+ Contract None => Any
32
+ def before_configuration
33
+ @leaves.clear
34
+
35
+ app.add_to_config_context :resources, &method(:root_collector)
36
+ app.add_to_config_context :collection, &method(:register_collector)
37
+ end
38
+
39
+ Contract Symbol, LazyCollectorStep => Any
40
+ def register_collector(label, endpoint)
41
+ @collectors_by_name[label] = endpoint
42
+ end
43
+
44
+ Contract Symbol => Any
45
+ def collector_value(label)
46
+ @values_by_name[label]
47
+ end
48
+
49
+ Contract ResourceList => ResourceList
50
+ def manipulate_resource_list(resources)
51
+ @root_collector.realize!(resources)
52
+
53
+ ctx = StepContext.new
54
+ leaves = @leaves.dup
55
+
56
+ @collectors_by_name.each do |k, v|
57
+ @values_by_name[k] = v.value(ctx)
58
+ leaves.delete v
59
+ end
60
+
61
+ # Execute code paths
62
+ leaves.each do |v|
63
+ v.value(ctx)
64
+ end
65
+
66
+ # Inject descriptors
67
+ resources + ctx.descriptors.map { |d| d.to_resource(app) }
68
+ end
69
+
70
+ helpers do
71
+ def collection(label)
72
+ extensions[:collections].collector_value(label)
73
+ end
74
+
75
+ def pagination
76
+ current_resource.data.pagination
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,30 @@
1
+ require 'middleman-core/core_extensions/collections/lazy_step'
2
+
3
+ module Middleman
4
+ module CoreExtensions
5
+ module Collections
6
+ class LazyCollectorRoot < BasicObject
7
+ def initialize(parent)
8
+ @data = nil
9
+ @parent = parent
10
+ end
11
+
12
+ def realize!(data)
13
+ @data = data
14
+ end
15
+
16
+ def value(_ctx=nil)
17
+ @data
18
+ end
19
+
20
+ def leaves
21
+ @parent.leaves
22
+ end
23
+
24
+ def method_missing(name, *args, &block)
25
+ LazyCollectorStep.new(name, args, block, self)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,48 @@
1
+ module Middleman
2
+ module CoreExtensions
3
+ module Collections
4
+ class LazyCollectorStep < BasicObject
5
+ DELEGATE = [:hash, :eql?]
6
+
7
+ def initialize(name, args, block, parent=nil)
8
+ @name = name
9
+ @args = args
10
+ @block = block
11
+
12
+ @parent = parent
13
+ @result = nil
14
+
15
+ leaves << self
16
+ end
17
+
18
+ def leaves
19
+ @parent.leaves
20
+ end
21
+
22
+ def value(ctx=nil)
23
+ data = @parent.value(ctx)
24
+
25
+ original_block = @block
26
+
27
+ b = if ctx
28
+ ::Proc.new do |*args|
29
+ ctx.instance_exec(*args, &original_block)
30
+ end
31
+ else
32
+ original_block
33
+ end if original_block
34
+
35
+ data.send(@name, *@args.deep_dup, &b)
36
+ end
37
+
38
+ def method_missing(name, *args, &block)
39
+ return ::Kernel.send(name, *args, &block) if DELEGATE.include? name
40
+
41
+ leaves.delete self
42
+
43
+ LazyCollectorStep.new(name, args, block, self)
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,59 @@
1
+ require 'active_support/core_ext/object/deep_dup'
2
+ require 'middleman-core/util'
3
+
4
+ module Middleman
5
+ module Pagination
6
+ module ArrayHelpers
7
+ def per_page(per_page)
8
+ return to_enum(__method__, per_page) unless block_given?
9
+
10
+ parts = if per_page.respond_to? :call
11
+ per_page.call(dup)
12
+ else
13
+ each_slice(per_page).reduce([]) do |sum, items|
14
+ sum << items
15
+ end
16
+ end
17
+
18
+ num_pages = parts.length
19
+ collection = self
20
+
21
+ current_start_i = 0
22
+ parts.each_with_index do |items, i|
23
+ num = i + 1
24
+
25
+ meta = ::Middleman::Pagination.page_locals(
26
+ num,
27
+ num_pages,
28
+ collection,
29
+ items,
30
+ current_start_i
31
+ )
32
+
33
+ yield items, num, meta, num >= num_pages
34
+
35
+ current_start_i += items.length
36
+ end
37
+ end
38
+ end
39
+
40
+ def self.page_locals(page_num, num_pages, collection, items, page_start)
41
+ per_page = items.length
42
+
43
+ # Index into collection of the last item of this page
44
+ page_end = (page_start + per_page) - 1
45
+
46
+ ::Middleman::Util.recursively_enhance(page_number: page_num,
47
+ num_pages: num_pages,
48
+ per_page: per_page,
49
+
50
+ # The range of item numbers on this page
51
+ # (1-based, for showing "Items X to Y of Z")
52
+ page_start: page_start + 1,
53
+ page_end: [page_end + 1, collection.length].min,
54
+
55
+ # Use "collection" in templates.
56
+ collection: collection)
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,26 @@
1
+ module Middleman
2
+ module CoreExtensions
3
+ module Collections
4
+ class StepContext
5
+ def self.add_to_context(name, &func)
6
+ send(:define_method, :"_internal_#{name}", &func)
7
+ end
8
+
9
+ attr_reader :descriptors
10
+
11
+ def initialize
12
+ @descriptors = []
13
+ end
14
+
15
+ def method_missing(name, *args, &block)
16
+ internal = :"_internal_#{name}"
17
+ if respond_to?(internal)
18
+ @descriptors << send(internal, *args, &block)
19
+ else
20
+ super
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -33,7 +33,7 @@ module Middleman
33
33
 
34
34
  # Setup data files before anything else so they are available when
35
35
  # parsing config.rb
36
- app.files.changed(:data, &@data_store.method(:update_files))
36
+ app.files.on_change(:data, &@data_store.method(:update_files))
37
37
  end
38
38
 
39
39
  def after_configuration
@@ -11,7 +11,7 @@ class Padrino::Helpers::OutputHelpers::ErbHandler
11
11
  raw = block.call(*args)
12
12
  captured = template.instance_variable_get(:@_out_buf)
13
13
  self.output_buffer = buf_was
14
- engine_matches?(block) ? captured : raw
14
+ engine_matches?(block) && !captured.empty? ? captured : raw
15
15
  end
16
16
  end
17
17
 
@@ -35,7 +35,6 @@ class Middleman::CoreExtensions::DefaultHelpers < ::Middleman::Extension
35
35
 
36
36
  # The helpers
37
37
  helpers do
38
-
39
38
  # Make all block content html_safe
40
39
  def content_tag(name, content=nil, options=nil, &block)
41
40
  # safe_content_tag(name, content, options, &block)
@@ -27,7 +27,7 @@ module Middleman::CoreExtensions
27
27
  end
28
28
 
29
29
  def before_configuration
30
- app.files.changed(:source, &method(:clear_data))
30
+ app.files.on_change(:source, &method(:clear_data))
31
31
  end
32
32
 
33
33
  # @return Array<Middleman::Sitemap::Resource>
@@ -90,7 +90,14 @@ module Middleman::CoreExtensions
90
90
 
91
91
  return [data, nil] if ::Middleman::Util.binary?(full_path)
92
92
 
93
- content = File.read(full_path)
93
+ # Avoid weird race condition when a file is renamed.
94
+ content = begin
95
+ File.read(full_path)
96
+ rescue ::EOFError
97
+ rescue ::IOError
98
+ rescue ::Errno::ENOENT
99
+ ''
100
+ end
94
101
 
95
102
  begin
96
103
  if content =~ /\A.*coding:/
@@ -115,7 +122,7 @@ module Middleman::CoreExtensions
115
122
  # @return [Array<Hash, String>]
116
123
  Contract String, Pathname => Maybe[[Hash, String]]
117
124
  def parse_yaml_front_matter(content, full_path)
118
- yaml_regex = /\A(---\s*\n.*?\n?)^(---\s*$\n?)/m
125
+ yaml_regex = /\A(---\s*\n.*?\n?)^((---|\.\.\.)\s*$\n?)/m
119
126
  if content =~ yaml_regex
120
127
  content = content.sub(yaml_regex, '')
121
128
 
@@ -23,7 +23,7 @@ class Middleman::CoreExtensions::Internationalization < ::Middleman::Extension
23
23
 
24
24
  # Setup data files before anything else so they are available when
25
25
  # parsing config.rb
26
- app.files.changed(:locales, &method(:on_file_changed))
26
+ app.files.on_change(:locales, &method(:on_file_changed))
27
27
 
28
28
  @maps = {}
29
29
  @mount_at_root = options[:mount_at_root].nil? ? langs.first : options[:mount_at_root]
@@ -59,12 +59,12 @@ class Middleman::CoreExtensions::Internationalization < ::Middleman::Extension
59
59
 
60
60
  if lang_suffix
61
61
  super(suffixed_partial_name) ||
62
- super(File.join(locals_dir, suffixed_partial_name)) ||
63
- super(partials_path) ||
64
- super
62
+ super(File.join(locals_dir, suffixed_partial_name)) ||
63
+ super(partials_path) ||
64
+ super
65
65
  else
66
66
  super(partials_path) ||
67
- super
67
+ super
68
68
  end
69
69
  end
70
70
  end
@@ -82,8 +82,7 @@ class Middleman::CoreExtensions::Internationalization < ::Middleman::Extension
82
82
 
83
83
  resources.each do |resource|
84
84
  # If it uses file extension localization
85
- if parse_locale_extension(resource.path)
86
- result = parse_locale_extension(resource.path)
85
+ if result = parse_locale_extension(resource.path)
87
86
  ext_lang, path, page_id = result
88
87
  new_resources << build_resource(path, resource.path, page_id, ext_lang)
89
88
  # If it's a "localizable template"
@@ -12,7 +12,7 @@ module Middleman::CoreExtensions
12
12
  end
13
13
 
14
14
  def after_configuration
15
- app.use ::Rack::ShowExceptions if app.config[:show_exceptions]
15
+ app.use ::Rack::ShowExceptions if !app.build? && app.config[:show_exceptions]
16
16
  end
17
17
  end
18
18
  end
@@ -238,7 +238,7 @@ module Middleman
238
238
  @options[k] = v
239
239
  end
240
240
 
241
- yield @options if block_given?
241
+ yield @options, self if block_given?
242
242
 
243
243
  @options.all_settings.each do |o|
244
244
  next unless o.options[:required] && !o.value_set?
@@ -16,8 +16,6 @@ class Middleman::Extensions::AutomaticImageSizes < ::Middleman::Extension
16
16
  # @return [String]
17
17
  def image_tag(path, params={})
18
18
  if !params.key?(:width) && !params.key?(:height) && !path.include?('://')
19
- params[:alt] ||= ''
20
-
21
19
  real_path = path.dup
22
20
  real_path = File.join(config[:images_dir], real_path) unless real_path.start_with?('/')
23
21
 
@@ -75,7 +75,9 @@ module Middleman
75
75
  end
76
76
 
77
77
  # Render using Tilt
78
- content = template.render(context, locs, &block)
78
+ content = ::Middleman::Util.instrument 'render.tilt', path: path do
79
+ template.render(context, locs, &block)
80
+ end
79
81
 
80
82
  # Allow hooks to manipulate the result after render
81
83
  @app.class.callbacks_for_hook(:after_render).each do |callback|
@@ -37,7 +37,8 @@ module Middleman
37
37
  end
38
38
 
39
39
  # Recursive method to find a file in parent directories
40
- def findup(filename, cwd=Pathname.new(Dir.pwd))
40
+ def findup(filename, cwd=Dir.pwd)
41
+ cwd = Pathname(cwd)
41
42
  return cwd.to_s if (cwd + filename).exist?
42
43
  return false if cwd.root?
43
44
  findup(filename, cwd.parent)
@@ -40,7 +40,7 @@ module Middleman
40
40
  return if @instrumenting.is_a?(String) && @instrumenting != 'instrument' && !message.include?(@instrumenting)
41
41
 
42
42
  evt = ActiveSupport::Notifications::Event.new(message, *args)
43
- info "== Instrument (#{evt.name.sub(/.middleman$/, '')}): #{evt.duration}ms"
43
+ info "== Instrument (#{evt.name.sub(/.middleman$/, '')}): #{evt.duration}ms\n#{args.last}"
44
44
  end
45
45
  end
46
46
  end
@@ -39,7 +39,7 @@ module Middleman
39
39
  build_path = 'Not built' if ignored?
40
40
  props['Build Path'] = build_path if @resource.path != build_path
41
41
  props['URL'] = content_tag(:a, @resource.url, href: @resource.url) unless ignored?
42
- props['Source File'] = @resource.source_file ? @resource.source_file[:full_path].to_s : 'Dynamic'
42
+ props['Source File'] = @resource.source_file ? @resource.source_file[:full_path].to_s.sub(/^#{Regexp.escape(ENV['MM_ROOT'] + '/')}/, '') : 'Dynamic'
43
43
 
44
44
  data = @resource.data
45
45
  props['Data'] = data.inspect unless data.empty?
@@ -120,7 +120,7 @@ module Middleman
120
120
  end
121
121
  end
122
122
 
123
- app.files.changed :reload do
123
+ app.files.on_change :reload do
124
124
  $mm_reload = true
125
125
  @webrick.stop
126
126
  end