middleman-more 3.0.14 → 3.1.0.beta.1

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.
Files changed (65) hide show
  1. data/features/asset_hash.feature +29 -0
  2. data/features/clean_build.feature +3 -3
  3. data/features/helpers_link_to.feature +4 -4
  4. data/features/i18n_force_locale.feature +13 -0
  5. data/features/i18n_preview.feature +14 -1
  6. data/features/markdown.feature +3 -2
  7. data/features/markdown_redcarpet.feature +21 -0
  8. data/features/markdown_redcarpet_in_haml.feature +42 -0
  9. data/features/minify_javascript.feature +2 -2
  10. data/features/partials_dir.feature +30 -0
  11. data/features/sass-assets-paths.feature +1 -1
  12. data/fixtures/default-partials-dir-app/source/_partial.html.erb +1 -0
  13. data/fixtures/default-partials-dir-app/source/index.html.erb +2 -0
  14. data/fixtures/i18n-default-app/locales/en.yml +4 -0
  15. data/fixtures/i18n-default-app/locales/es.yml +8 -0
  16. data/fixtures/i18n-default-app/source/localizable/index.html.erb +5 -0
  17. data/fixtures/i18n-force-locale/config.rb +13 -0
  18. data/fixtures/i18n-force-locale/locales/en.yml +3 -0
  19. data/fixtures/i18n-force-locale/locales/es.yml +3 -0
  20. data/fixtures/i18n-force-locale/locales/fr.yml +3 -0
  21. data/fixtures/i18n-force-locale/source/index.haml +2 -0
  22. data/fixtures/markdown-app/config.rb +1 -0
  23. data/fixtures/markdown-frontmatter-options-app/config.rb +1 -0
  24. data/fixtures/markdown-frontmatter-options-app/source/smarty_pants-default.html.markdown +5 -0
  25. data/fixtures/markdown-frontmatter-options-app/source/smarty_pants-off.html.markdown +7 -0
  26. data/fixtures/markdown-frontmatter-options-app/source/smarty_pants-on.html.markdown +7 -0
  27. data/fixtures/markdown-frontmatter-options-app/source/tables-default.html.markdown +8 -0
  28. data/fixtures/markdown-frontmatter-options-app/source/tables-off.html.markdown +10 -0
  29. data/fixtures/markdown-frontmatter-options-app/source/tables-on.html.markdown +10 -0
  30. data/{lib/middleman-more/templates/smacss/source/stylesheets/_0.site-settings.scss → fixtures/markdown-in-haml-app/config.rb} +0 -0
  31. data/fixtures/markdown-in-haml-app/source/images/blank.gif +0 -0
  32. data/fixtures/markdown-in-haml-app/source/link_target.html.markdown +4 -0
  33. data/fixtures/partials-dir-app/source/index.html.erb +2 -0
  34. data/fixtures/partials-dir-app/source/nested/partials/_partial.html.erb +1 -0
  35. data/fixtures/partials-dir-app/source/partials/_partial.html.erb +1 -0
  36. data/fixtures/sass-assets-path-app/assets/stylesheets/{_shared-asset.sass → _shared-asset-sass.sass} +1 -1
  37. data/fixtures/sass-assets-path-app/source/stylesheets/plain.css.sass +1 -1
  38. data/lib/middleman-more/core_extensions/compass.rb +22 -22
  39. data/lib/middleman-more/core_extensions/default_helpers.rb +36 -13
  40. data/lib/middleman-more/core_extensions/i18n.rb +31 -6
  41. data/lib/middleman-more/extensions/asset_hash.rb +30 -17
  42. data/lib/middleman-more/extensions/asset_host.rb +11 -8
  43. data/lib/middleman-more/extensions/automatic_image_sizes.rb +4 -8
  44. data/lib/middleman-more/extensions/directory_indexes.rb +2 -5
  45. data/lib/middleman-more/extensions/gzip.rb +18 -19
  46. data/lib/middleman-more/extensions/minify_css.rb +11 -4
  47. data/lib/middleman-more/extensions/minify_javascript.rb +1 -1
  48. data/lib/middleman-more/templates/smacss/source/_footer.haml +1 -1
  49. data/lib/middleman-more/templates/smacss/source/stylesheets/base/README.markdown +11 -0
  50. data/lib/middleman-more/templates/smacss/source/stylesheets/base/base.scss +1 -0
  51. data/lib/middleman-more/templates/smacss/source/stylesheets/base/normalize.scss +375 -0
  52. data/lib/middleman-more/templates/smacss/source/stylesheets/layout/README.markdown +9 -0
  53. data/lib/middleman-more/templates/smacss/source/stylesheets/modules/README.markdown +9 -0
  54. data/lib/middleman-more/templates/smacss/source/stylesheets/states/README.markdown +12 -0
  55. data/lib/middleman-more/templates/smacss/source/stylesheets/style.css.scss +12 -7
  56. data/lib/middleman-more.rb +1 -5
  57. data/middleman-more.gemspec +3 -4
  58. metadata +75 -50
  59. data/lib/middleman-more/core_extensions/assets.rb +0 -43
  60. data/lib/middleman-more/extensions/minify_css/rainpress.rb +0 -168
  61. data/lib/middleman-more/templates/smacss/source/stylesheets/_1.base.scss +0 -2
  62. data/lib/middleman-more/templates/smacss/source/stylesheets/_2.layout.scss +0 -2
  63. data/lib/middleman-more/templates/smacss/source/stylesheets/_3.states.scss +0 -2
  64. data/lib/middleman-more/templates/smacss/source/stylesheets/_4.themes.scss +0 -2
  65. data/lib/middleman-more/templates/smacss/source/stylesheets/modules/_btn.scss +0 -2
@@ -1,3 +1,6 @@
1
+ require "i18n"
2
+ require "i18n/backend/fallbacks"
3
+
1
4
  module Middleman
2
5
  module CoreExtensions
3
6
 
@@ -9,12 +12,23 @@ module Middleman
9
12
 
10
13
  # Once registerd
11
14
  def registered(app, options={})
12
- app.set :locales_dir, "locales"
15
+ app.config.define_setting :locales_dir, "locales", 'The directory holding your locale configurations'
13
16
 
14
17
  # Needed for helpers as well
15
18
  app.after_configuration do
16
19
  Localizer.new(self, options)
17
20
  end
21
+
22
+ app.helpers do
23
+ def t(*args)
24
+ ::I18n.t(*args)
25
+ end
26
+ end
27
+
28
+ # See https://github.com/svenfuchs/i18n/wiki/Fallbacks
29
+ unless options[:no_fallbacks]
30
+ ::I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks)
31
+ end
18
32
  end
19
33
  alias :included :registered
20
34
  end
@@ -28,7 +42,7 @@ module Middleman
28
42
  @app = app
29
43
  @locales_glob = File.join(app.locales_dir, "**", "*.{rb,yml,yaml}")
30
44
 
31
- # File.fnmatch doesn't support brackets: {rb,yml}
45
+ # File.fnmatch doesn't support brackets: {rb,yml,yaml}
32
46
  regex = @locales_glob.sub(/\./, '\.').sub(File.join("**", "*"), ".*").sub(/\//, '\/').sub("{rb,yml,yaml}", "rb|ya?ml")
33
47
  @locales_regex = %r{^#{regex}}
34
48
 
@@ -43,6 +57,12 @@ module Middleman
43
57
  @templates_dir = @options[:templates_dir] || "localizable"
44
58
  @mount_at_root = @options.has_key?(:mount_at_root) ? @options[:mount_at_root] : langs.first
45
59
 
60
+ ::I18n.default_locale = @mount_at_root
61
+ # Reset fallbacks to fall back to our new default
62
+ if ::I18n.respond_to? :fallbacks
63
+ ::I18n.fallbacks = ::I18n::Locale::Fallbacks.new
64
+ end
65
+
46
66
  if !@app.build?
47
67
  logger.info "== Locales: #{langs.join(", ")} (Default #{@mount_at_root})"
48
68
  end
@@ -60,13 +80,15 @@ module Middleman
60
80
  end
61
81
 
62
82
  instance_vars = Proc.new do
63
- ::I18n.locale = lang
64
83
  @lang = lang
65
84
  @page_id = page_id
66
85
  end
67
86
 
68
- locals = { :lang => lang, :page_id => page_id }
69
- { :blocks => [instance_vars], :locals => locals }
87
+ locals = { :lang => lang,
88
+ :page_id => page_id }
89
+ { :blocks => [instance_vars],
90
+ :locals => locals,
91
+ :options => { :lang => lang } }
70
92
  end
71
93
 
72
94
  @app.sitemap.register_resource_list_manipulator(
@@ -111,10 +133,11 @@ module Middleman
111
133
 
112
134
  page_id = File.basename(resource.path, File.extname(resource.path))
113
135
 
136
+ old_locale = ::I18n.locale
114
137
  langs.map do |lang|
115
138
  ::I18n.locale = lang
116
139
 
117
- localized_page_id = ::I18n.t("paths.#{page_id}", :default => page_id)
140
+ localized_page_id = ::I18n.t("paths.#{page_id}", :default => page_id, :fallback => [])
118
141
  path = resource.path.sub(@templates_dir, "")
119
142
 
120
143
  # Build lang path
@@ -139,6 +162,8 @@ module Middleman
139
162
 
140
163
  new_resources << p
141
164
  end
165
+ ::I18n.locale = old_locale
166
+
142
167
  end
143
168
 
144
169
  resources + new_resources
@@ -1,27 +1,29 @@
1
1
  module Middleman
2
2
  module Extensions
3
3
  module AssetHash
4
- class << self
5
- def registered(app, options={})
4
+ class Extension < ::Middleman::Extension
5
+ option :exts, %w(.jpg .jpeg .png .gif .js .css .otf .woff .eot .ttf .svg), "List of extensions that get asset hashes appended to them."
6
+ option :ignore, [], "Regexes of filenames to skip adding asset hashes to"
7
+
8
+ def initialize(app, options_hash={})
9
+ super
10
+
6
11
  require 'digest/sha1'
7
12
  require 'rack/test'
8
13
  require 'uri'
14
+ end
9
15
 
10
- exts = options[:exts] || %w(.jpg .jpeg .png .gif .js .css .otf .woff .eot .ttf .svg)
11
-
16
+ def after_configuration
12
17
  # Allow specifying regexes to ignore, plus always ignore apple touch icons
13
- ignore = Array(options[:ignore]) << /^apple-touch-icon/
18
+ ignore = Array(options.ignore) + [/^apple-touch-icon/]
14
19
 
15
- app.ready do
16
- sitemap.register_resource_list_manipulator(
17
- :asset_hash,
18
- AssetHashManager.new(self, exts, ignore)
19
- )
20
+ app.sitemap.register_resource_list_manipulator(
21
+ :asset_hash,
22
+ AssetHashManager.new(app, options.exts, ignore)
23
+ )
20
24
 
21
- use Middleware, :exts => exts, :middleman_app => self, :ignore => ignore
22
- end
25
+ app.use Middleware, :exts => options.exts, :middleman_app => app, :ignore => ignore
23
26
  end
24
- alias :included :registered
25
27
  end
26
28
 
27
29
  # Central class for managing asset_hash extension
@@ -35,13 +37,24 @@ module Middleman
35
37
  # Update the main sitemap resource list
36
38
  # @return [void]
37
39
  def manipulate_resource_list(resources)
38
- resources.each do |resource|
40
+ # Process resources in order: binary images and fonts, then SVG, then JS/CSS.
41
+ # This is so by the time we get around to the text files (which may reference
42
+ # images and fonts) the static assets' hashes are already calculated.
43
+ rack_client = ::Rack::Test::Session.new(@app.class.to_rack_app)
44
+ resources.sort_by do |a|
45
+ if %w(.svg).include? a.ext
46
+ 0
47
+ elsif %w(.js .css).include? a.ext
48
+ 1
49
+ else
50
+ -1
51
+ end
52
+ end.each do |resource|
39
53
  next unless @exts.include? resource.ext
40
54
  next if @ignore.any? { |ignore| Middleman::Util.path_match(ignore, resource.destination_path) }
41
55
 
42
56
  # Render through the Rack interface so middleware and mounted apps get a shot
43
- rack_client = ::Rack::Test::Session.new(@app.class)
44
- response = rack_client.get(URI.escape(resource.destination_path), {}, { "bypass_asset_hash" => true })
57
+ response = rack_client.get(URI.escape(resource.destination_path), {}, { "bypass_asset_hash" => "true" })
45
58
  raise "#{resource.path} should be in the sitemap!" unless response.status == 200
46
59
 
47
60
  digest = Digest::SHA1.hexdigest(response.body)[0..7]
@@ -66,7 +79,7 @@ module Middleman
66
79
  status, headers, response = @rack_app.call(env)
67
80
 
68
81
  # We don't want to use this middleware when rendering files to figure out their hash!
69
- return [status, headers, response] if env["bypass_asset_hash"]
82
+ return [status, headers, response] if env["bypass_asset_hash"] == 'true'
70
83
 
71
84
  path = @middleman_app.full_path(env["PATH_INFO"])
72
85
  dirpath = Pathname.new(File.dirname(path))
@@ -9,9 +9,12 @@ module Middleman
9
9
  class << self
10
10
 
11
11
  # Once registered
12
- def registered(app)
13
- # Default to no host
14
- app.set :asset_host, false
12
+ def registered(app, options={})
13
+ app.config.define_setting :asset_host, false, 'The asset host to use, or false for no asset host, or a Proc to determine asset host'
14
+
15
+ if options[:host]
16
+ config[:asset_host] = options[:host]
17
+ end
15
18
 
16
19
  # Include methods
17
20
  app.send :include, InstanceMethods
@@ -30,12 +33,12 @@ module Middleman
30
33
  # @return [String]
31
34
  def asset_url(path, prefix="")
32
35
  original_output = super
33
- return original_output unless asset_host
36
+ return original_output unless config[:asset_host]
34
37
 
35
- asset_prefix = if asset_host.is_a?(Proc)
36
- asset_host.call(original_output)
37
- elsif asset_host.is_a?(String)
38
- asset_host
38
+ asset_prefix = if config[:asset_host].is_a?(Proc)
39
+ config[:asset_host].call(original_output)
40
+ elsif config[:asset_host].is_a?(String)
41
+ config[:asset_host]
39
42
  end
40
43
 
41
44
  File.join(asset_prefix, original_output)
@@ -30,29 +30,25 @@ module Middleman
30
30
  # @param [Hash] params
31
31
  # @return [String]
32
32
  def image_tag(path, params={})
33
- params[:supported_extensions] ||= %w(.png .jpg .jpeg .bmp .gif)
34
-
35
- if !params.has_key?(:width) && !params.has_key?(:height) && !path.include?("://") &&
36
- params[:supported_extensions].include?(File.extname(path).downcase)
37
-
33
+ if !params.has_key?(:width) && !params.has_key?(:height) && !path.include?("://")
38
34
  params[:alt] ||= ""
39
35
 
40
36
  real_path = path
41
37
  real_path = File.join(images_dir, real_path) unless real_path.start_with?('/')
42
38
  full_path = File.join(source_dir, real_path)
43
39
 
44
- if File.exists? full_path
40
+ if File.exists?(full_path)
45
41
  begin
46
42
  width, height = ::FastImage.size(full_path, :raise_on_failure => true)
47
43
  params[:width] = width
48
44
  params[:height] = height
45
+ rescue FastImage::UnknownImageType
46
+ # No message, it's just not supported
49
47
  rescue
50
48
  warn "Couldn't determine dimensions for image #{path}: #{$!.message}"
51
49
  end
52
50
  end
53
51
  end
54
-
55
- params = params.delete_if {|key| key == :supported_extensions }
56
52
 
57
53
  super(path, params)
58
54
  end
@@ -40,13 +40,10 @@ module Middleman
40
40
  File.extname(index_file) != resource.ext
41
41
 
42
42
  # Check if frontmatter turns directory_index off
43
- d = resource.data
44
- next if d && d["directory_index"] == false
43
+ next if resource.data[:directory_index] == false
45
44
 
46
45
  # Check if file metadata (options set by "page" in config.rb) turns directory_index off
47
- if resource.metadata[:options] && resource.metadata[:options][:directory_index] == false
48
- next
49
- end
46
+ next if resource.metadata[:options][:directory_index] == false
50
47
 
51
48
  resource.destination_path = resource.destination_path.chomp(File.extname(index_file)) + new_index_path
52
49
  end
@@ -15,34 +15,33 @@ module Middleman::Extensions
15
15
  # Pass the :exts options to customize which file extensions get zipped (defaults
16
16
  # to .html, .htm, .js and .css.
17
17
  #
18
- module Gzip
19
- class << self
20
- def registered(app, options={})
21
- exts = options[:exts] || %w(.js .css .html .htm)
18
+ class Gzip < ::Middleman::Extension
19
+ option :exts, %w(.js .css .html .htm), 'File extensions to Gzip when building.'
22
20
 
23
- app.after_build do |builder|
21
+ def initialize(app, options_hash={})
22
+ super
24
23
 
25
- paths = ::Middleman::Util.all_files_under(self.class.inst.build_dir)
26
- paths.each do |path|
27
- next unless exts.include? path.extname
24
+ gzip_ext = self
28
25
 
29
- output_filename, old_size, new_size = Middleman::Extensions::Gzip.gzip_file(path.to_s)
26
+ app.after_build do |builder|
27
+ paths = ::Middleman::Util.all_files_under(self.class.inst.build_dir)
28
+ paths.each do |path|
29
+ next unless gzip_ext.options.exts.include? path.extname
30
30
 
31
- if output_filename
32
- size_change_word = (old_size - new_size) > 0 ? 'smaller' : 'larger'
33
- old_locale = I18n.locale
34
- I18n.locale = :en # use the english localizations for printing out file sizes to make sure the localizations exist
35
- builder.say_status :gzip, "#{output_filename} (#{number_to_human_size((old_size - new_size).abs)} #{size_change_word})"
36
- I18n.locale = old_locale
37
- end
31
+ output_filename, old_size, new_size = gzip_ext.gzip_file(path.to_s)
32
+
33
+ if output_filename
34
+ size_change_word = (old_size - new_size) > 0 ? 'smaller' : 'larger'
35
+ old_locale = I18n.locale
36
+ I18n.locale = :en # use the english localizations for printing out file sizes to make sure the localizations exist
37
+ builder.say_status :gzip, "#{output_filename} (#{number_to_human_size((old_size - new_size).abs)} #{size_change_word})"
38
+ I18n.locale = old_locale
38
39
  end
39
40
  end
40
41
  end
41
-
42
- alias :included :registered
43
42
  end
44
43
 
45
- def self.gzip_file(path)
44
+ def gzip_file(path)
46
45
  input_file = File.open(path, 'rb').read
47
46
  output_filename = path + '.gz'
48
47
  input_file_time = File.mtime(path)
@@ -10,15 +10,14 @@ module Middleman
10
10
 
11
11
  # Once registered
12
12
  def registered(app, options={})
13
- app.set :css_compressor, false
13
+ app.config.define_setting :css_compressor, nil, 'Set the CSS compressor to use. Deprecated in favor of the :compressor option when activating :minify_css'
14
14
 
15
15
  ignore = Array(options[:ignore]) << /\.min\./
16
16
  inline = options[:inline] || false
17
17
 
18
18
  app.after_configuration do
19
- chosen_compressor = css_compressor || options[:compressor] || begin
20
- require "middleman-more/extensions/minify_css/rainpress"
21
- ::Rainpress
19
+ chosen_compressor = config[:css_compressor] || options[:compressor] || begin
20
+ ::Middleman::Extensions::MinifyCss::SassCompressor
22
21
  end
23
22
 
24
23
  # Setup Rack middleware to minify CSS
@@ -30,6 +29,14 @@ module Middleman
30
29
  alias :included :registered
31
30
  end
32
31
 
32
+ class SassCompressor
33
+ def self.compress(style, options = {})
34
+ root_node = ::Sass::SCSS::CssParser.new(style, 'middleman-css-input', 1).parse
35
+ root_node.options = { :style => :compressed }
36
+ root_node.render.strip
37
+ end
38
+ end
39
+
33
40
  # Rack middleware to look for CSS and compress it
34
41
  class Rack
35
42
 
@@ -10,7 +10,7 @@ module Middleman
10
10
 
11
11
  # Once registered
12
12
  def registered(app, options={})
13
- app.set :js_compressor, false
13
+ app.config.define_setting :js_compressor, nil, 'Set the JS compressor to use. Deprecated in favor of the :compressor option when activating :minify_js'
14
14
 
15
15
  ignore = Array(options[:ignore]) << /\.min\./
16
16
  inline = options[:inline] || false
@@ -1 +1 @@
1
- %footer &copy; 2012
1
+ %footer &copy; 2013
@@ -0,0 +1,11 @@
1
+ # SMACSS
2
+
3
+ ### Base
4
+
5
+ > A Base rule is applied to an element using an element selector, a descendent selector, or a child selector, along with any pseudo-classes. It doesn’t include any class or ID selectors. It is defining the default styling for how that element should look in all occurrences on the page.
6
+
7
+ > - SMACSS, Jonathan Snook
8
+
9
+ Place files here that impact top-level elements to apply global styles.
10
+
11
+ This template includes [`normalize.css`](http://necolas.github.com/normalize.css/) to give consistent base styles for all browsers.