middleman-more 3.1.0.beta.1 → 3.1.0.beta.2

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.
@@ -1,174 +1,150 @@
1
- require "i18n"
2
- require "i18n/backend/fallbacks"
1
+ class Middleman::CoreExtensions::Internationalization < ::Middleman::Extension
2
+ option :no_fallbacks, false, "Disable I18n fallbacks"
3
+ option :langs, nil, "List of langs, will autodiscover by default"
4
+ option :lang_map, {}, "Language shortname map"
5
+ option :path, "/:locale/", "URL prefix path"
6
+ option :templates_dir, "localizable", "Location of templates to be localized"
7
+ option :mount_at_root, nil, "Mount a specific language at the root of the site"
8
+ option :data, "locales", "The directory holding your locale configurations"
9
+
10
+ def initialize(app, options_hash={}, &block)
11
+ super
12
+
13
+ # See https://github.com/svenfuchs/i18n/wiki/Fallbacks
14
+ unless options[:no_fallbacks]
15
+ require "i18n/backend/fallbacks"
16
+ ::I18n::Backend::Simple.send(:include, ::I18n::Backend::Fallbacks)
17
+ end
3
18
 
4
- module Middleman
5
- module CoreExtensions
19
+ app.config.define_setting :locales_dir, "locales", 'The directory holding your locale configurations'
20
+ end
6
21
 
7
- # i18n Namespace
8
- module Internationalization
22
+ def after_configuration
23
+ @locales_glob = File.join(app.config[:locals_dir] || options[:data], "**", "*.{rb,yml,yaml}")
9
24
 
10
- # Setup extension
11
- class << self
25
+ # File.fnmatch doesn't support brackets: {rb,yml,yaml}
26
+ regex = @locales_glob.sub(/\./, '\.').sub(File.join("**", "*"), ".*").sub(/\//, '\/').sub("{rb,yml,yaml}", "rb|ya?ml")
27
+ @locales_regex = %r{^#{regex}}
12
28
 
13
- # Once registerd
14
- def registered(app, options={})
15
- app.config.define_setting :locales_dir, "locales", 'The directory holding your locale configurations'
29
+ @maps = {}
16
30
 
17
- # Needed for helpers as well
18
- app.after_configuration do
19
- Localizer.new(self, options)
20
- end
31
+ ::I18n.load_path += Dir[File.join(app.root, @locales_glob)]
32
+ ::I18n.reload!
21
33
 
22
- app.helpers do
23
- def t(*args)
24
- ::I18n.t(*args)
25
- end
26
- end
34
+ @mount_at_root = options[:mount_at_root].nil? ? langs.first : options[:mount_at_root]
27
35
 
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
32
- end
33
- alias :included :registered
34
- end
36
+ ::I18n.default_locale = @mount_at_root
37
+ # Reset fallbacks to fall back to our new default
38
+ if ::I18n.respond_to? :fallbacks
39
+ ::I18n.fallbacks = ::I18n::Locale::Fallbacks.new
40
+ end
35
41
 
36
- # Central class for managing i18n extension
37
- class Localizer
38
- attr_reader :app
39
- delegate :logger, :to => :app
40
-
41
- def initialize(app, options={})
42
- @app = app
43
- @locales_glob = File.join(app.locales_dir, "**", "*.{rb,yml,yaml}")
44
-
45
- # File.fnmatch doesn't support brackets: {rb,yml,yaml}
46
- regex = @locales_glob.sub(/\./, '\.').sub(File.join("**", "*"), ".*").sub(/\//, '\/').sub("{rb,yml,yaml}", "rb|ya?ml")
47
- @locales_regex = %r{^#{regex}}
48
-
49
- @maps = {}
50
- @options = options
51
-
52
- ::I18n.load_path += Dir[File.join(app.root, @locales_glob)]
53
- ::I18n.reload!
54
-
55
- @lang_map = @options[:lang_map] || {}
56
- @path = @options[:path] || "/:locale/"
57
- @templates_dir = @options[:templates_dir] || "localizable"
58
- @mount_at_root = @options.has_key?(:mount_at_root) ? @options[:mount_at_root] : langs.first
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
-
66
- if !@app.build?
67
- logger.info "== Locales: #{langs.join(", ")} (Default #{@mount_at_root})"
68
- end
69
-
70
- # Don't output localizable files
71
- @app.ignore File.join(@templates_dir, "**")
72
-
73
- @app.sitemap.provides_metadata_for_path do |url|
74
- if d = get_localization_data(url)
75
- lang, page_id = d
76
- else
77
- # Default to the @mount_at_root lang
78
- page_id = nil
79
- lang = @mount_at_root
80
- end
81
-
82
- instance_vars = Proc.new do
83
- @lang = lang
84
- @page_id = page_id
85
- end
86
-
87
- locals = { :lang => lang,
88
- :page_id => page_id }
89
- { :blocks => [instance_vars],
90
- :locals => locals,
91
- :options => { :lang => lang } }
92
- end
93
-
94
- @app.sitemap.register_resource_list_manipulator(
95
- :i18n,
96
- self
97
- )
98
-
99
- @app.files.changed(&method(:on_file_changed))
100
- @app.files.deleted(&method(:on_file_changed))
101
- end
42
+ if !app.build?
43
+ logger.info "== Locales: #{langs.join(", ")} (Default #{@mount_at_root})"
44
+ end
102
45
 
103
- def on_file_changed(file)
104
- if @locales_regex =~ file
105
- ::I18n.reload!
106
- end
107
- end
46
+ # Don't output localizable files
47
+ app.ignore File.join(options[:templates_dir], "**")
108
48
 
109
- def langs
110
- if @options[:langs]
111
- Array(@options[:langs]).map(&:to_sym)
112
- else
113
- Dir[File.join(@app.root, @locales_glob)].map { |file|
114
- File.basename(file).sub(/\.ya?ml$/, "").sub(/\.rb$/, "")
115
- }.sort.map(&:to_sym)
116
- end
117
- end
49
+ app.sitemap.provides_metadata_for_path do |url|
50
+ if d = get_localization_data(url)
51
+ lang, page_id = d
52
+ else
53
+ # Default to the @mount_at_root lang
54
+ page_id = nil
55
+ lang = @mount_at_root
56
+ end
118
57
 
119
- def get_localization_data(path)
120
- @_localization_data ||= {}
121
- @_localization_data[path]
122
- end
58
+ instance_vars = Proc.new do
59
+ @lang = lang
60
+ @page_id = page_id
61
+ end
62
+
63
+ locals = { :lang => lang,
64
+ :page_id => page_id }
65
+ { :blocks => [instance_vars],
66
+ :locals => locals,
67
+ :options => { :lang => lang } }
68
+ end
123
69
 
124
- # Update the main sitemap resource list
125
- # @return [void]
126
- def manipulate_resource_list(resources)
127
- @_localization_data = {}
70
+ app.files.changed(&method(:on_file_changed))
71
+ app.files.deleted(&method(:on_file_changed))
72
+ end
128
73
 
129
- new_resources = []
74
+ helpers do
75
+ def t(*args)
76
+ ::I18n.t(*args)
77
+ end
78
+ end
130
79
 
131
- resources.each do |resource|
132
- next unless File.fnmatch(File.join(@templates_dir, "**"), resource.path)
80
+ delegate :logger, :to => :app
133
81
 
134
- page_id = File.basename(resource.path, File.extname(resource.path))
82
+ def on_file_changed(file)
83
+ if @locales_regex =~ file
84
+ ::I18n.reload!
85
+ end
86
+ end
135
87
 
136
- old_locale = ::I18n.locale
137
- langs.map do |lang|
138
- ::I18n.locale = lang
88
+ def langs
89
+ if options[:langs]
90
+ Array(options[:langs]).map(&:to_sym)
91
+ else
92
+ Dir[File.join(app.root, @locales_glob)].map { |file|
93
+ File.basename(file).sub(/\.ya?ml$/, "").sub(/\.rb$/, "")
94
+ }.sort.map(&:to_sym)
95
+ end
96
+ end
139
97
 
140
- localized_page_id = ::I18n.t("paths.#{page_id}", :default => page_id, :fallback => [])
141
- path = resource.path.sub(@templates_dir, "")
98
+ def get_localization_data(path)
99
+ @_localization_data ||= {}
100
+ @_localization_data[path]
101
+ end
142
102
 
143
- # Build lang path
144
- if @mount_at_root == lang
145
- prefix = "/"
146
- else
147
- replacement = @lang_map.has_key?(lang) ? @lang_map[lang] : lang
148
- prefix = @path.sub(":locale", replacement.to_s)
149
- end
103
+ # Update the main sitemap resource list
104
+ # @return [void]
105
+ def manipulate_resource_list(resources)
106
+ @_localization_data = {}
150
107
 
151
- path = ::Middleman::Util.normalize_path(
152
- File.join(prefix, path.sub(page_id, localized_page_id))
153
- )
108
+ new_resources = []
154
109
 
155
- @_localization_data[path] = [lang, path, localized_page_id]
110
+ resources.each do |resource|
111
+ next unless File.fnmatch(File.join(options[:templates_dir], "**"), resource.path)
156
112
 
157
- p = ::Middleman::Sitemap::Resource.new(
158
- @app.sitemap,
159
- path
160
- )
161
- p.proxy_to(resource.path)
113
+ page_id = File.basename(resource.path, File.extname(resource.path))
162
114
 
163
- new_resources << p
164
- end
165
- ::I18n.locale = old_locale
115
+ old_locale = ::I18n.locale
116
+ langs.map do |lang|
117
+ ::I18n.locale = lang
166
118
 
167
- end
119
+ localized_page_id = ::I18n.t("paths.#{page_id}", :default => page_id, :fallback => [])
120
+ path = resource.path.sub(options[:templates_dir], "")
168
121
 
169
- resources + new_resources
122
+ # Build lang path
123
+ if @mount_at_root == lang
124
+ prefix = "/"
125
+ else
126
+ replacement = options[:lang_map].has_key?(lang) ? options[:lang_map][lang] : lang
127
+ prefix = options[:path].sub(":locale", replacement.to_s)
170
128
  end
129
+
130
+ path = ::Middleman::Util.normalize_path(
131
+ File.join(prefix, path.sub(page_id, localized_page_id))
132
+ )
133
+
134
+ @_localization_data[path] = [lang, path, localized_page_id]
135
+
136
+ p = ::Middleman::Sitemap::Resource.new(
137
+ app.sitemap,
138
+ path
139
+ )
140
+ p.proxy_to(resource.path)
141
+
142
+ new_resources << p
171
143
  end
144
+ ::I18n.locale = old_locale
145
+
172
146
  end
147
+
148
+ resources + new_resources
173
149
  end
174
150
  end
@@ -1,124 +1,104 @@
1
- module Middleman
2
- module Extensions
3
- module AssetHash
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
-
11
- require 'digest/sha1'
12
- require 'rack/test'
13
- require 'uri'
14
- end
1
+ class Middleman::Extensions::AssetHash < ::Middleman::Extension
2
+ option :exts, %w(.jpg .jpeg .png .gif .js .css .otf .woff .eot .ttf .svg), "List of extensions that get asset hashes appended to them."
3
+ option :ignore, [], "Regexes of filenames to skip adding asset hashes to"
15
4
 
16
- def after_configuration
17
- # Allow specifying regexes to ignore, plus always ignore apple touch icons
18
- ignore = Array(options.ignore) + [/^apple-touch-icon/]
5
+ def initialize(app, options_hash={}, &block)
6
+ super
19
7
 
20
- app.sitemap.register_resource_list_manipulator(
21
- :asset_hash,
22
- AssetHashManager.new(app, options.exts, ignore)
23
- )
8
+ require 'digest/sha1'
9
+ require 'rack/test'
10
+ require 'uri'
11
+ end
24
12
 
25
- app.use Middleware, :exts => options.exts, :middleman_app => app, :ignore => ignore
26
- end
27
- end
13
+ def after_configuration
14
+ # Allow specifying regexes to ignore, plus always ignore apple touch icons
15
+ @ignore = Array(options.ignore) + [/^apple-touch-icon/]
28
16
 
29
- # Central class for managing asset_hash extension
30
- class AssetHashManager
31
- def initialize(app, exts, ignore)
32
- @app = app
33
- @exts = exts
34
- @ignore = ignore
35
- end
17
+ app.use Middleware, :exts => options.exts, :middleman_app => app, :ignore => @ignore
18
+ end
36
19
 
37
- # Update the main sitemap resource list
38
- # @return [void]
39
- def manipulate_resource_list(resources)
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|
53
- next unless @exts.include? resource.ext
54
- next if @ignore.any? { |ignore| Middleman::Util.path_match(ignore, resource.destination_path) }
20
+ # Update the main sitemap resource list
21
+ # @return [void]
22
+ def manipulate_resource_list(resources)
23
+ # Process resources in order: binary images and fonts, then SVG, then JS/CSS.
24
+ # This is so by the time we get around to the text files (which may reference
25
+ # images and fonts) the static assets' hashes are already calculated.
26
+ rack_client = ::Rack::Test::Session.new(app.class.to_rack_app)
27
+ resources.sort_by do |a|
28
+ if %w(.svg).include? a.ext
29
+ 0
30
+ elsif %w(.js .css).include? a.ext
31
+ 1
32
+ else
33
+ -1
34
+ end
35
+ end.each do |resource|
36
+ next unless options.exts.include? resource.ext
37
+ next if @ignore.any? { |ignore| Middleman::Util.path_match(ignore, resource.destination_path) }
55
38
 
56
- # Render through the Rack interface so middleware and mounted apps get a shot
57
- response = rack_client.get(URI.escape(resource.destination_path), {}, { "bypass_asset_hash" => "true" })
58
- raise "#{resource.path} should be in the sitemap!" unless response.status == 200
39
+ # Render through the Rack interface so middleware and mounted apps get a shot
40
+ response = rack_client.get(URI.escape(resource.destination_path), {}, { "bypass_asset_hash" => "true" })
41
+ raise "#{resource.path} should be in the sitemap!" unless response.status == 200
59
42
 
60
- digest = Digest::SHA1.hexdigest(response.body)[0..7]
43
+ digest = Digest::SHA1.hexdigest(response.body)[0..7]
61
44
 
62
- resource.destination_path = resource.destination_path.sub(/\.(\w+)$/) { |ext| "-#{digest}#{ext}" }
63
- end
64
- end
65
- end
66
-
67
- # The asset hash middleware is responsible for rewriting references to
68
- # assets to include their new, hashed name.
69
- class Middleware
70
- def initialize(app, options={})
71
- @rack_app = app
72
- @exts = options[:exts]
73
- @ignore = options[:ignore]
74
- @exts_regex_text = @exts.map {|e| Regexp.escape(e) }.join('|')
75
- @middleman_app = options[:middleman_app]
76
- end
45
+ resource.destination_path = resource.destination_path.sub(/\.(\w+)$/) { |ext| "-#{digest}#{ext}" }
46
+ end
47
+ end
77
48
 
78
- def call(env)
79
- status, headers, response = @rack_app.call(env)
49
+ # The asset hash middleware is responsible for rewriting references to
50
+ # assets to include their new, hashed name.
51
+ class Middleware
52
+ def initialize(app, options={})
53
+ @rack_app = app
54
+ @exts = options[:exts]
55
+ @ignore = options[:ignore]
56
+ @exts_regex_text = @exts.map {|e| Regexp.escape(e) }.join('|')
57
+ @middleman_app = options[:middleman_app]
58
+ end
80
59
 
81
- # We don't want to use this middleware when rendering files to figure out their hash!
82
- return [status, headers, response] if env["bypass_asset_hash"] == 'true'
60
+ def call(env)
61
+ status, headers, response = @rack_app.call(env)
83
62
 
84
- path = @middleman_app.full_path(env["PATH_INFO"])
85
- dirpath = Pathname.new(File.dirname(path))
63
+ # We don't want to use this middleware when rendering files to figure out their hash!
64
+ return [status, headers, response] if env["bypass_asset_hash"] == 'true'
86
65
 
87
- if path =~ /(^\/$)|(\.(htm|html|php|css|js)$)/
88
- body = ::Middleman::Util.extract_response_text(response)
66
+ path = @middleman_app.full_path(env["PATH_INFO"])
67
+ dirpath = Pathname.new(File.dirname(path))
89
68
 
90
- if body
91
- # TODO: This regex will change some paths in plan HTML (not in a tag) - is that OK?
92
- body.gsub! /([=\'\"\(]\s*)([^\s\'\"\)]+(#{@exts_regex_text}))/ do |match|
93
- opening_character = $1
94
- asset_path = $2
69
+ if path =~ /(^\/$)|(\.(htm|html|php|css|js)$)/
70
+ body = ::Middleman::Util.extract_response_text(response)
95
71
 
96
- relative_path = Pathname.new(asset_path).relative?
72
+ if body
73
+ # TODO: This regex will change some paths in plan HTML (not in a tag) - is that OK?
74
+ body.gsub!(/([=\'\"\(]\s*)([^\s\'\"\)]+(#{@exts_regex_text}))/) do |match|
75
+ opening_character = $1
76
+ asset_path = $2
97
77
 
98
- asset_path = dirpath.join(asset_path).to_s if relative_path
78
+ relative_path = Pathname.new(asset_path).relative?
99
79
 
100
- if @ignore.any? { |r| asset_path.match(r) }
101
- match
102
- elsif asset_page = @middleman_app.sitemap.find_resource_by_path(asset_path)
103
- replacement_path = "/#{asset_page.destination_path}"
104
- replacement_path = Pathname.new(replacement_path).relative_path_from(dirpath).to_s if relative_path
80
+ asset_path = dirpath.join(asset_path).to_s if relative_path
105
81
 
106
- "#{opening_character}#{replacement_path}"
107
- else
108
- match
109
- end
110
- end
82
+ if @ignore.any? { |r| asset_path.match(r) }
83
+ match
84
+ elsif asset_page = @middleman_app.sitemap.find_resource_by_path(asset_path)
85
+ replacement_path = "/#{asset_page.destination_path}"
86
+ replacement_path = Pathname.new(replacement_path).relative_path_from(dirpath).to_s if relative_path
111
87
 
112
- status, headers, response = Rack::Response.new(body, status, headers).finish
88
+ "#{opening_character}#{replacement_path}"
89
+ else
90
+ match
113
91
  end
114
92
  end
115
- [status, headers, response]
93
+
94
+ status, headers, response = Rack::Response.new(body, status, headers).finish
116
95
  end
117
96
  end
97
+ [status, headers, response]
118
98
  end
119
99
  end
120
- end
121
100
 
101
+ end
122
102
 
123
103
  # =================Temp Generate Test data==============================
124
104
  # ["jpg", "png", "gif"].each do |ext|
@@ -1,49 +1,50 @@
1
- # Extensions namespace
2
- module Middleman
3
- module Extensions
4
1
 
5
- # Asset Host module
6
- module AssetHost
2
+ # Asset Host module
3
+ class Middleman::Extensions::AssetHost < ::Middleman::Extension
4
+ option :host, nil, 'The asset host to use, or false for no asset host, or a Proc to determine asset host'
7
5
 
8
- # Setup extension
9
- class << self
6
+ def initialize(app, options_hash={}, &block)
7
+ super
10
8
 
11
- # Once registered
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'
9
+ # Backwards compatible API
10
+ app.config.define_setting :asset_host, nil, 'The asset host to use, or false for no asset host, or a Proc to determine asset host'
14
11
 
15
- if options[:host]
16
- config[:asset_host] = options[:host]
12
+ app.compass_config do |config|
13
+ if asset_host = extensions[:asset_host].host
14
+ if asset_host.is_a?(Proc)
15
+ config.asset_host(&asset_host)
16
+ else
17
+ config.asset_host do |asset|
18
+ asset_host
17
19
  end
18
-
19
- # Include methods
20
- app.send :include, InstanceMethods
21
20
  end
22
-
23
- alias :included :registered
24
21
  end
22
+ end
23
+ end
25
24
 
26
- # Asset Host Instance Methods
27
- module InstanceMethods
28
-
29
- # Override default asset url helper to include asset hosts
30
- #
31
- # @param [String] path
32
- # @param [String] prefix
33
- # @return [String]
34
- def asset_url(path, prefix="")
35
- original_output = super
36
- return original_output unless config[:asset_host]
37
-
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]
42
- end
25
+ def host
26
+ app.config[:asset_host] || options[:host]
27
+ end
43
28
 
44
- File.join(asset_prefix, original_output)
45
- end
29
+ helpers do
30
+ # Override default asset url helper to include asset hosts
31
+ #
32
+ # @param [String] path
33
+ # @param [String] prefix
34
+ # @return [String]
35
+ def asset_url(path, prefix="")
36
+ controller = extensions[:asset_host]
37
+
38
+ original_output = super
39
+ return original_output unless controller.host
40
+
41
+ asset_prefix = if controller.host.is_a?(Proc)
42
+ controller.host.call(original_output)
43
+ elsif controller.host.is_a?(String)
44
+ controller.host
46
45
  end
46
+
47
+ File.join(asset_prefix, original_output)
47
48
  end
48
49
  end
49
50
  end