middleman-core 4.0.0.beta.2 → 4.0.0.rc.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.
- checksums.yaml +4 -4
- data/features/builder.feature +9 -1
- data/features/collections.feature +43 -2
- data/features/data.feature +7 -0
- data/features/extension_hooks.feature +13 -0
- data/features/front-matter-neighbor.feature +0 -11
- data/features/front-matter.feature +0 -22
- data/features/markdown_kramdown_in_slim.feature +42 -0
- data/fixtures/extension-hooks-app/config.rb +39 -0
- data/fixtures/extension-hooks-app/source/index.html.erb +9 -0
- data/fixtures/frontmatter-app/source/front-matter-line-2.html.erb +4 -1
- data/fixtures/frontmatter-neighbor-app/config.rb +3 -3
- data/fixtures/frontmatter-settings-neighbor-app/config.rb +4 -4
- data/fixtures/markdown-in-slim-app/config.rb +0 -0
- data/fixtures/markdown-in-slim-app/source/images/blank.gif +0 -0
- data/fixtures/markdown-in-slim-app/source/link_target.html.markdown +4 -0
- data/fixtures/more-traversal-app/source/layout.erb +1 -1
- data/fixtures/nested-data-app/data/examples/withcontent.yaml +11 -0
- data/fixtures/nested-data-app/source/extracontent.html.haml.erb +4 -0
- data/fixtures/traversal-app/source/layout.erb +1 -1
- data/lib/middleman-core/application.rb +7 -3
- data/lib/middleman-core/builder.rb +2 -1
- data/lib/middleman-core/configuration.rb +0 -1
- data/lib/middleman-core/contracts.rb +0 -10
- data/lib/middleman-core/core_extensions/collections.rb +30 -6
- data/lib/middleman-core/core_extensions/data.rb +4 -4
- data/lib/middleman-core/core_extensions/file_watcher.rb +1 -1
- data/lib/middleman-core/core_extensions/front_matter.rb +10 -104
- data/lib/middleman-core/core_extensions/show_exceptions.rb +1 -1
- data/lib/middleman-core/extension_manager.rb +2 -1
- data/lib/middleman-core/extensions/asset_hash.rb +2 -1
- data/lib/middleman-core/extensions/asset_host.rb +1 -1
- data/lib/middleman-core/extensions/external_pipeline.rb +4 -1
- data/lib/middleman-core/extensions/minify_css.rb +1 -1
- data/lib/middleman-core/extensions/minify_javascript.rb +1 -1
- data/lib/middleman-core/extensions/relative_assets.rb +1 -1
- data/lib/middleman-core/extensions.rb +1 -1
- data/lib/middleman-core/file_renderer.rb +6 -4
- data/lib/middleman-core/meta_pages/sitemap_resource.rb +1 -1
- data/lib/middleman-core/meta_pages/templates/config.html.erb +14 -14
- data/lib/middleman-core/meta_pages.rb +6 -1
- data/lib/middleman-core/preview_server.rb +21 -2
- data/lib/middleman-core/rack.rb +5 -3
- data/lib/middleman-core/renderers/haml.rb +22 -6
- data/lib/middleman-core/renderers/kramdown.rb +10 -3
- data/lib/middleman-core/renderers/liquid.rb +22 -3
- data/lib/middleman-core/renderers/redcarpet.rb +7 -5
- data/lib/middleman-core/renderers/sass.rb +1 -5
- data/lib/middleman-core/renderers/slim.rb +16 -12
- data/lib/middleman-core/sitemap/extensions/ignores.rb +2 -0
- data/lib/middleman-core/sitemap/extensions/on_disk.rb +2 -0
- data/lib/middleman-core/sitemap/extensions/proxies.rb +18 -3
- data/lib/middleman-core/sitemap/extensions/redirects.rb +2 -0
- data/lib/middleman-core/sitemap/extensions/request_endpoints.rb +2 -0
- data/lib/middleman-core/sitemap/resource.rb +24 -17
- data/lib/middleman-core/sitemap/store.rb +1 -0
- data/lib/middleman-core/sources/source_watcher.rb +26 -1
- data/lib/middleman-core/step_definitions/builder_steps.rb +8 -8
- data/lib/middleman-core/step_definitions/middleman_steps.rb +8 -2
- data/lib/middleman-core/step_definitions/server_steps.rb +17 -18
- data/lib/middleman-core/step_definitions.rb +0 -1
- data/lib/middleman-core/template_context.rb +2 -2
- data/lib/middleman-core/util/data.rb +153 -0
- data/lib/middleman-core/util.rb +14 -45
- data/lib/middleman-core/version.rb +1 -1
- data/middleman-core.gemspec +3 -2
- data/spec/middleman-core/util_spec.rb +3 -23
- metadata +37 -26
- data/fixtures/frontmatter-app/source/json-front-matter-2.php.erb +0 -7
- data/fixtures/frontmatter-app/source/json-front-matter-encoding.html.erb +0 -7
- data/fixtures/frontmatter-app/source/json-front-matter-line-2.html.erb +0 -7
- data/fixtures/frontmatter-app/source/json-front-matter.html.erb +0 -6
- data/fixtures/frontmatter-neighbor-app/source/json-front-matter-2.php.erb +0 -2
- data/fixtures/frontmatter-neighbor-app/source/json-front-matter-2.php.erb.frontmatter +0 -4
- data/fixtures/frontmatter-neighbor-app/source/json-front-matter.html.erb +0 -1
- data/fixtures/frontmatter-neighbor-app/source/json-front-matter.html.erb.frontmatter +0 -4
@@ -1,24 +1,18 @@
|
|
1
|
-
|
1
|
+
# Core Pathname library used for traversal
|
2
2
|
require 'pathname'
|
3
3
|
|
4
|
-
#
|
5
|
-
require '
|
4
|
+
# DbC
|
5
|
+
require 'middleman-core/contracts'
|
6
|
+
|
7
|
+
require 'active_support/core_ext/hash/keys'
|
6
8
|
|
7
|
-
|
8
|
-
require 'active_support/json'
|
9
|
+
require 'middleman-core/util/data'
|
9
10
|
|
10
11
|
# Extensions namespace
|
11
12
|
module Middleman::CoreExtensions
|
12
13
|
class FrontMatter < ::Middleman::Extension
|
13
14
|
# Try to run after routing but before directory_indexes
|
14
|
-
self.resource_list_manipulator_priority =
|
15
|
-
|
16
|
-
YAML_ERRORS = [StandardError]
|
17
|
-
|
18
|
-
# https://github.com/tenderlove/psych/issues/23
|
19
|
-
if defined?(Psych) && defined?(Psych::SyntaxError)
|
20
|
-
YAML_ERRORS << Psych::SyntaxError
|
21
|
-
end
|
15
|
+
self.resource_list_manipulator_priority = 10
|
22
16
|
|
23
17
|
def initialize(app, options_hash={}, &block)
|
24
18
|
super
|
@@ -34,9 +28,9 @@ module Middleman::CoreExtensions
|
|
34
28
|
Contract ResourceList => ResourceList
|
35
29
|
def manipulate_resource_list(resources)
|
36
30
|
resources.each do |resource|
|
37
|
-
next if resource.
|
31
|
+
next if resource.file_descriptor.nil?
|
38
32
|
|
39
|
-
fmdata = data(resource.
|
33
|
+
fmdata = data(resource.file_descriptor[:full_path].to_s).first.dup
|
40
34
|
|
41
35
|
# Copy over special options
|
42
36
|
# TODO: Should we make people put these under "options" instead of having
|
@@ -71,7 +65,7 @@ module Middleman::CoreExtensions
|
|
71
65
|
|
72
66
|
return [{}, nil] unless file
|
73
67
|
|
74
|
-
@cache[file[:full_path]] ||=
|
68
|
+
@cache[file[:full_path]] ||= ::Middleman::Util::Data.parse(file[:full_path])
|
75
69
|
end
|
76
70
|
|
77
71
|
Contract ArrayOf[IsA['Middleman::SourceFile']], ArrayOf[IsA['Middleman::SourceFile']] => Any
|
@@ -80,93 +74,5 @@ module Middleman::CoreExtensions
|
|
80
74
|
@cache.delete(file[:full_path])
|
81
75
|
end
|
82
76
|
end
|
83
|
-
|
84
|
-
# Get the frontmatter and plain content from a file
|
85
|
-
# @param [String] path
|
86
|
-
# @return [Array<Middleman::Util::IndifferentHash, String>]
|
87
|
-
Contract Pathname => [Hash, Maybe[String]]
|
88
|
-
def frontmatter_and_content(full_path)
|
89
|
-
data = {}
|
90
|
-
|
91
|
-
return [data, nil] if ::Middleman::Util.binary?(full_path)
|
92
|
-
|
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
|
101
|
-
|
102
|
-
begin
|
103
|
-
if content =~ /\A.*coding:/
|
104
|
-
lines = content.split(/\n/)
|
105
|
-
lines.shift
|
106
|
-
content = lines.join("\n")
|
107
|
-
end
|
108
|
-
|
109
|
-
result = parse_yaml_front_matter(content, full_path) || parse_json_front_matter(content, full_path)
|
110
|
-
return result if result
|
111
|
-
rescue
|
112
|
-
# Probably a binary file, move on
|
113
|
-
end
|
114
|
-
|
115
|
-
[data, content]
|
116
|
-
end
|
117
|
-
|
118
|
-
private
|
119
|
-
|
120
|
-
# Parse YAML frontmatter out of a string
|
121
|
-
# @param [String] content
|
122
|
-
# @return [Array<Hash, String>]
|
123
|
-
Contract String, Pathname => Maybe[[Hash, String]]
|
124
|
-
def parse_yaml_front_matter(content, full_path)
|
125
|
-
yaml_regex = /\A(---\s*\n.*?\n?)^((---|\.\.\.)\s*$\n?)/m
|
126
|
-
if content =~ yaml_regex
|
127
|
-
content = content.sub(yaml_regex, '')
|
128
|
-
|
129
|
-
begin
|
130
|
-
data = YAML.load($1) || {}
|
131
|
-
data = data.symbolize_keys
|
132
|
-
rescue *YAML_ERRORS => e
|
133
|
-
app.logger.error "YAML Exception parsing #{full_path}: #{e.message}"
|
134
|
-
return nil
|
135
|
-
end
|
136
|
-
else
|
137
|
-
return nil
|
138
|
-
end
|
139
|
-
|
140
|
-
[data, content]
|
141
|
-
rescue
|
142
|
-
[{}, content]
|
143
|
-
end
|
144
|
-
|
145
|
-
# Parse JSON frontmatter out of a string
|
146
|
-
# @param [String] content
|
147
|
-
# @return [Array<Hash, String>]
|
148
|
-
Contract String, Pathname => Maybe[[Hash, String]]
|
149
|
-
def parse_json_front_matter(content, full_path)
|
150
|
-
json_regex = /\A(;;;\s*\n.*?\n?)^(;;;\s*$\n?)/m
|
151
|
-
|
152
|
-
if content =~ json_regex
|
153
|
-
content = content.sub(json_regex, '')
|
154
|
-
|
155
|
-
begin
|
156
|
-
json = ($1 + $2).sub(';;;', '{').sub(';;;', '}')
|
157
|
-
data = ::ActiveSupport::JSON.decode(json).symbolize_keys
|
158
|
-
rescue => e
|
159
|
-
app.logger.error "JSON Exception parsing #{full_path}: #{e.message}"
|
160
|
-
return nil
|
161
|
-
end
|
162
|
-
|
163
|
-
else
|
164
|
-
return nil
|
165
|
-
end
|
166
|
-
|
167
|
-
[data, content]
|
168
|
-
rescue
|
169
|
-
[{}, content]
|
170
|
-
end
|
171
77
|
end
|
172
78
|
end
|
@@ -11,7 +11,7 @@ module Middleman::CoreExtensions
|
|
11
11
|
app.config.define_setting :show_exceptions, ENV['TEST'] ? false : true, 'Whether to catch and display exceptions'
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
14
|
+
def ready
|
15
15
|
app.use ::Rack::ShowExceptions if !app.build? && app.config[:show_exceptions]
|
16
16
|
end
|
17
17
|
end
|
@@ -3,13 +3,14 @@ module Middleman
|
|
3
3
|
extend Forwardable
|
4
4
|
|
5
5
|
def_delegator :@app, :logger
|
6
|
-
def_delegators :@activated, :[]
|
6
|
+
def_delegators :@activated, :[], :each
|
7
7
|
|
8
8
|
def initialize(app)
|
9
9
|
@app = app
|
10
10
|
@activated = {}
|
11
11
|
|
12
12
|
manager = self
|
13
|
+
|
13
14
|
{
|
14
15
|
before_sitemap: :before_sitemap,
|
15
16
|
initialized: :before_configuration
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'addressable/uri'
|
2
2
|
require 'middleman-core/util'
|
3
|
+
require 'middleman-core/rack'
|
3
4
|
|
4
5
|
class Middleman::Extensions::AssetHash < ::Middleman::Extension
|
5
6
|
option :exts, %w(.jpg .jpeg .png .gif .webp .js .css .otf .woff .woff2 .eot .ttf .svg), 'List of extensions that get asset hashes appended to them.'
|
@@ -16,7 +17,7 @@ class Middleman::Extensions::AssetHash < ::Middleman::Extension
|
|
16
17
|
def after_configuration
|
17
18
|
# Allow specifying regexes to ignore, plus always ignore apple touch icons
|
18
19
|
@ignore = Array(options.ignore) + [/^apple-touch-icon/]
|
19
|
-
|
20
|
+
|
20
21
|
app.use ::Middleman::Middleware::InlineURLRewriter,
|
21
22
|
id: :asset_hash,
|
22
23
|
url_extensions: options.exts,
|
@@ -7,7 +7,7 @@ class Middleman::Extensions::AssetHost < ::Middleman::Extension
|
|
7
7
|
option :sources, %w(.htm .html .php .css .js), 'List of extensions that are searched for bustable assets.'
|
8
8
|
option :ignore, [], 'Regexes of filenames to skip adding query strings to'
|
9
9
|
|
10
|
-
def
|
10
|
+
def ready
|
11
11
|
app.use ::Middleman::Middleware::InlineURLRewriter,
|
12
12
|
id: :asset_host,
|
13
13
|
url_extensions: options.exts,
|
@@ -16,7 +16,7 @@ class Middleman::Extensions::ExternalPipeline < ::Middleman::Extension
|
|
16
16
|
latency: options[:latency]
|
17
17
|
end
|
18
18
|
|
19
|
-
def
|
19
|
+
def ready
|
20
20
|
if app.build?
|
21
21
|
logger.info "== Executing: `#{options[:command]}`"
|
22
22
|
watch_command!
|
@@ -33,5 +33,8 @@ class Middleman::Extensions::ExternalPipeline < ::Middleman::Extension
|
|
33
33
|
logger.info "== External: #{without_newline}" if without_newline.length > 0
|
34
34
|
end
|
35
35
|
end
|
36
|
+
rescue ::Errno::ENOENT => e
|
37
|
+
logger.error "== External: Command failed with message: #{e.message}"
|
38
|
+
exit(1)
|
36
39
|
end
|
37
40
|
end
|
@@ -9,7 +9,7 @@ class Middleman::Extensions::MinifyCss < ::Middleman::Extension
|
|
9
9
|
SassCompressor
|
10
10
|
}, 'Set the CSS compressor to use.'
|
11
11
|
|
12
|
-
def
|
12
|
+
def ready
|
13
13
|
# Setup Rack middleware to minify CSS
|
14
14
|
app.use Rack, compressor: options[:compressor],
|
15
15
|
ignore: Array(options[:ignore]) + [/\.min\./],
|
@@ -9,7 +9,7 @@ class Middleman::Extensions::MinifyJavascript < ::Middleman::Extension
|
|
9
9
|
::Uglifier.new
|
10
10
|
}, 'Set the JS compressor to use.'
|
11
11
|
|
12
|
-
def
|
12
|
+
def ready
|
13
13
|
# Setup Rack middleware to minify CSS
|
14
14
|
app.use Rack, compressor: options[:compressor],
|
15
15
|
ignore: Array(options[:ignore]) + [/\.min\./],
|
@@ -12,7 +12,7 @@ class Middleman::Extensions::RelativeAssets < ::Middleman::Extension
|
|
12
12
|
require 'middleman-core/middleware/inline_url_rewriter'
|
13
13
|
end
|
14
14
|
|
15
|
-
def
|
15
|
+
def ready
|
16
16
|
app.use ::Middleman::Middleware::InlineURLRewriter,
|
17
17
|
id: :asset_hash,
|
18
18
|
url_extensions: options.exts,
|
@@ -106,7 +106,7 @@ module Middleman
|
|
106
106
|
# A flattened list of all extensions which are automatically activated
|
107
107
|
# @return [Array<Symbol>] A list of extension names which are automatically activated.
|
108
108
|
def auto_activated
|
109
|
-
@auto_activate.values.
|
109
|
+
@auto_activate.values.map(&:to_a).flatten.map(&:name)
|
110
110
|
end
|
111
111
|
|
112
112
|
# @api private
|
@@ -53,6 +53,7 @@ module Middleman
|
|
53
53
|
extension = File.extname(path)
|
54
54
|
options = opts.merge(options_for_ext(extension))
|
55
55
|
options[:outvar] ||= '@_out_buf'
|
56
|
+
options[:context] = context
|
56
57
|
options.delete(:layout)
|
57
58
|
|
58
59
|
# Overwrite with frontmatter options
|
@@ -66,9 +67,10 @@ module Middleman
|
|
66
67
|
end
|
67
68
|
|
68
69
|
# Read compiled template from disk or cache
|
69
|
-
template =
|
70
|
-
|
71
|
-
|
70
|
+
template = ::Tilt.new(path, 1, options) { body }
|
71
|
+
# template = cache.fetch(:compiled_template, extension, options, body) do
|
72
|
+
# ::Tilt.new(path, 1, options) { body }
|
73
|
+
# end
|
72
74
|
|
73
75
|
# Render using Tilt
|
74
76
|
content = ::Middleman::Util.instrument 'render.tilt', path: path do
|
@@ -76,7 +78,7 @@ module Middleman
|
|
76
78
|
end
|
77
79
|
|
78
80
|
# Allow hooks to manipulate the result after render
|
79
|
-
content = @app.callbacks_for(:
|
81
|
+
content = @app.callbacks_for(:after_render).reduce(content) do |sum, callback|
|
80
82
|
callback.call(sum, path, locs, template_class) || sum
|
81
83
|
end
|
82
84
|
|
@@ -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.
|
42
|
+
props['Source File'] = @resource.file_descriptor ? @resource.file_descriptor[: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?
|
@@ -29,22 +29,22 @@
|
|
29
29
|
|
30
30
|
<h2 id="extensions">Extensions</h2>
|
31
31
|
<ul class="extensions">
|
32
|
-
<% extension_config.each do |
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
32
|
+
<% [extension_config, auto_activated_config].each do |extensions| %>
|
33
|
+
<% extensions.each do |ext_name, configs| %>
|
34
|
+
<li>
|
35
|
+
<% registered_extensions.delete(ext_name) %>
|
36
|
+
|
37
|
+
<span class="extension active">:<%= ext_name %></span>
|
38
|
+
|
39
|
+
<% if configs && !configs.empty? %>
|
40
|
+
<ul class="settings">
|
41
|
+
<% configs.each do |setting| %>
|
42
|
+
<li class="setting"><%= setting.render %></li>
|
43
|
+
<% end %>
|
44
|
+
</ul>
|
43
45
|
<% end %>
|
44
|
-
</
|
46
|
+
</li>
|
45
47
|
<% end %>
|
46
|
-
</li>
|
47
|
-
|
48
48
|
<% end %>
|
49
49
|
|
50
50
|
<% registered_extensions.keys.each do |ext_name| %>
|
@@ -61,9 +61,13 @@ module Middleman
|
|
61
61
|
def config(_)
|
62
62
|
global_config = @middleman.config.all_settings.map { |c| ConfigSetting.new(c) }
|
63
63
|
extension_config = {}
|
64
|
+
auto_activated_config = {}
|
64
65
|
|
65
66
|
@middleman.extensions.each do |ext_name, extension|
|
66
|
-
|
67
|
+
if ::Middleman::Extensions.auto_activated.include? ext_name
|
68
|
+
auto_activated_config[ext_name] = extension_options(extension)
|
69
|
+
next
|
70
|
+
end
|
67
71
|
|
68
72
|
if extension.is_a?(Hash)
|
69
73
|
# Multiple instance extension
|
@@ -82,6 +86,7 @@ module Middleman
|
|
82
86
|
template('config.html.erb',
|
83
87
|
global_config: global_config,
|
84
88
|
extension_config: extension_config,
|
89
|
+
auto_activated_config: auto_activated_config,
|
85
90
|
registered_extensions: Middleman::Extensions.registered.dup)
|
86
91
|
end
|
87
92
|
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'webrick'
|
2
2
|
require 'webrick/https'
|
3
3
|
require 'openssl'
|
4
|
+
require 'socket'
|
4
5
|
require 'middleman-core/meta_pages'
|
5
6
|
require 'middleman-core/logger'
|
6
7
|
require 'middleman-core/rack'
|
@@ -123,9 +124,18 @@ module Middleman
|
|
123
124
|
]
|
124
125
|
|
125
126
|
# config.rb
|
126
|
-
files.watch :reload,
|
127
|
+
watcher = files.watch :reload,
|
127
128
|
path: root,
|
128
129
|
only: match_against
|
130
|
+
|
131
|
+
# Hack around node_modules in root.
|
132
|
+
watcher.listener.ignore(/^node_modules/)
|
133
|
+
|
134
|
+
# Hack around sass cache in root.
|
135
|
+
watcher.listener.ignore(/^\.sass-cache/)
|
136
|
+
|
137
|
+
# Hack around bundler cache in root.
|
138
|
+
watcher.listener.ignore(/^vendor\/bundle/)
|
129
139
|
end
|
130
140
|
end
|
131
141
|
|
@@ -200,7 +210,7 @@ module Middleman
|
|
200
210
|
begin
|
201
211
|
::WEBrick::HTTPServer.new(http_opts)
|
202
212
|
rescue Errno::EADDRINUSE
|
203
|
-
logger.error "== Port #{port} is unavailable. Either close the instance of Middleman already running on #{port} or start this Middleman on a new port with: --port=#{
|
213
|
+
logger.error "== Port #{port} is unavailable. Either close the instance of Middleman already running on #{port} or start this Middleman on a new port with: --port=#{unused_tcp_port}"
|
204
214
|
exit(1)
|
205
215
|
end
|
206
216
|
end
|
@@ -234,6 +244,15 @@ module Middleman
|
|
234
244
|
scheme = https? ? 'https' : 'http'
|
235
245
|
URI("#{scheme}://#{host}:#{@port}")
|
236
246
|
end
|
247
|
+
|
248
|
+
# Returns unused TCP port
|
249
|
+
# @return [Fixnum]
|
250
|
+
def unused_tcp_port
|
251
|
+
server = TCPServer.open(0)
|
252
|
+
port = server.addr[1]
|
253
|
+
server.close
|
254
|
+
port
|
255
|
+
end
|
237
256
|
end
|
238
257
|
|
239
258
|
class FilteredWebrickLog < ::WEBrick::Log
|
data/lib/middleman-core/rack.rb
CHANGED
@@ -4,6 +4,7 @@ require 'rack/lint'
|
|
4
4
|
require 'rack/head'
|
5
5
|
|
6
6
|
require 'middleman-core/util'
|
7
|
+
require 'middleman-core/logger'
|
7
8
|
require 'middleman-core/template_renderer'
|
8
9
|
|
9
10
|
# CSSPIE HTC File
|
@@ -73,8 +74,9 @@ module Middleman
|
|
73
74
|
# message.
|
74
75
|
#
|
75
76
|
# @param env
|
77
|
+
# @param [Rack::Request] req
|
76
78
|
# @param [Rack::Response] res
|
77
|
-
def process_request(env,
|
79
|
+
def process_request(env, req, res)
|
78
80
|
start_time = Time.now
|
79
81
|
|
80
82
|
request_path = URI.decode(env['PATH_INFO'].dup)
|
@@ -100,7 +102,7 @@ module Middleman
|
|
100
102
|
|
101
103
|
begin
|
102
104
|
# Write out the contents of the page
|
103
|
-
res.write resource.render
|
105
|
+
res.write resource.render({}, { rack: { request: req } })
|
104
106
|
|
105
107
|
# Valid content is a 200 status
|
106
108
|
res.status = 200
|
@@ -124,7 +126,7 @@ module Middleman
|
|
124
126
|
# Immediately send static file
|
125
127
|
def send_file(resource, env)
|
126
128
|
file = ::Rack::File.new nil
|
127
|
-
file.path = resource.
|
129
|
+
file.path = resource.file_descriptor[:full_path]
|
128
130
|
response = file.serving(env)
|
129
131
|
status = response[0]
|
130
132
|
response[1]['Content-Encoding'] = 'gzip' if %w(.svgz .gz).include?(resource.ext)
|
@@ -20,29 +20,45 @@ module Middleman
|
|
20
20
|
# thus making it impossible to pass our Middleman instance
|
21
21
|
# in. So we have to resort to heavy hackery :(
|
22
22
|
class HamlTemplate < ::Tilt::HamlTemplate
|
23
|
+
def initialize(*args, &block)
|
24
|
+
super
|
25
|
+
|
26
|
+
@context = @options[:context] if @options.key?(:context)
|
27
|
+
end
|
28
|
+
|
23
29
|
def prepare
|
24
30
|
end
|
25
31
|
|
26
32
|
def evaluate(scope, locals, &block)
|
27
|
-
|
28
|
-
|
29
|
-
options = @options.merge(filename: eval_file, line: line)
|
33
|
+
options = @options.merge(filename: eval_file, line: line, context: @context || scope)
|
30
34
|
@engine = ::Haml::Engine.new(data, options)
|
31
35
|
output = @engine.render(scope, locals, &block)
|
32
36
|
|
33
|
-
::Middleman::Renderers::Haml.last_haml_scope = nil
|
34
|
-
|
35
37
|
output
|
36
38
|
end
|
37
39
|
end
|
38
40
|
|
39
41
|
# Haml Renderer
|
40
42
|
class Haml < ::Middleman::Extension
|
41
|
-
cattr_accessor :last_haml_scope
|
42
43
|
|
43
44
|
def initialize(app, options={}, &block)
|
44
45
|
super
|
45
46
|
|
47
|
+
::Haml::Options.defaults[:context] = nil
|
48
|
+
::Haml::Options.send :attr_accessor, :context
|
49
|
+
|
50
|
+
[::Haml::Filters::Sass, ::Haml::Filters::Scss, ::Haml::Filters::Markdown].each do |f|
|
51
|
+
f.class_exec do
|
52
|
+
def self.render_with_options(text, compiler_options)
|
53
|
+
modified_options = options.dup
|
54
|
+
modified_options[:context] = compiler_options[:context]
|
55
|
+
|
56
|
+
text = template_class.new(nil, 1, modified_options) {text}.render
|
57
|
+
super(text, compiler_options)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
46
62
|
::Tilt.prefer(::Middleman::Renderers::HamlTemplate, :haml)
|
47
63
|
|
48
64
|
# Add haml helpers to context
|
@@ -4,10 +4,16 @@ module Middleman
|
|
4
4
|
module Renderers
|
5
5
|
# Our own Kramdown Tilt template that simply uses our custom renderer.
|
6
6
|
class KramdownTemplate < ::Tilt::KramdownTemplate
|
7
|
-
def
|
8
|
-
|
9
|
-
|
7
|
+
def initialize(*args, &block)
|
8
|
+
super
|
9
|
+
|
10
|
+
@context = @options[:context] if @options.key?(:context)
|
11
|
+
end
|
10
12
|
|
13
|
+
def evaluate(context, *)
|
14
|
+
MiddlemanKramdownHTML.scope = @context || context
|
15
|
+
|
16
|
+
@output ||= begin
|
11
17
|
output, warnings = MiddlemanKramdownHTML.convert(@engine.root, @engine.options)
|
12
18
|
@engine.warnings.concat(warnings)
|
13
19
|
output
|
@@ -38,6 +44,7 @@ module Middleman
|
|
38
44
|
|
39
45
|
attr = el.attr.dup
|
40
46
|
link = attr.delete('href')
|
47
|
+
|
41
48
|
scope.link_to(content, link, attr)
|
42
49
|
end
|
43
50
|
end
|
@@ -23,11 +23,30 @@ module Middleman
|
|
23
23
|
return resources unless app.extensions[:data]
|
24
24
|
|
25
25
|
resources.each do |resource|
|
26
|
-
next if resource.
|
27
|
-
next unless resource.
|
26
|
+
next if resource.file_descriptor.nil?
|
27
|
+
next unless resource.file_descriptor[:relative_path].to_s =~ %r{\.liquid$}
|
28
28
|
|
29
29
|
# Convert data object into a hash for liquid
|
30
|
-
resource.add_metadata locals: {
|
30
|
+
resource.add_metadata locals: {
|
31
|
+
data: stringify_recursive(app.extensions[:data].data_store.to_h)
|
32
|
+
}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def stringify_recursive(hash)
|
37
|
+
{}.tap do |h|
|
38
|
+
hash.each { |key, value| h[key.to_s] = map_value(value) }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def map_value(thing)
|
43
|
+
case thing
|
44
|
+
when Hash
|
45
|
+
stringify_recursive(thing)
|
46
|
+
when Array
|
47
|
+
thing.map { |v| map_value(v) }
|
48
|
+
else
|
49
|
+
thing
|
31
50
|
end
|
32
51
|
end
|
33
52
|
end
|
@@ -10,6 +10,12 @@ module Middleman
|
|
10
10
|
escape_html: :filter_html
|
11
11
|
}
|
12
12
|
|
13
|
+
def initialize(*args, &block)
|
14
|
+
super
|
15
|
+
|
16
|
+
@context = @options[:context] if @options.key?(:context)
|
17
|
+
end
|
18
|
+
|
13
19
|
# Overwrite built-in Tilt version.
|
14
20
|
# Don't overload :renderer option with smartypants
|
15
21
|
# Support renderer-level options
|
@@ -40,11 +46,7 @@ module Middleman
|
|
40
46
|
|
41
47
|
def evaluate(scope, _)
|
42
48
|
@output ||= begin
|
43
|
-
|
44
|
-
MiddlemanRedcarpetHTML.scope = ::Middleman::Renderers::Haml.last_haml_scope || scope
|
45
|
-
else
|
46
|
-
MiddlemanRedcarpetHTML.scope = scope
|
47
|
-
end
|
49
|
+
MiddlemanRedcarpetHTML.scope = @context || scope
|
48
50
|
|
49
51
|
@engine.render(data)
|
50
52
|
end
|
@@ -94,11 +94,7 @@ module Middleman
|
|
94
94
|
# Change Sass path, for url functions, to the build folder if we're building
|
95
95
|
# @return [Hash]
|
96
96
|
def sass_options
|
97
|
-
ctx =
|
98
|
-
::Middleman::Renderers::Haml.last_haml_scope || @context
|
99
|
-
else
|
100
|
-
@context
|
101
|
-
end
|
97
|
+
ctx = @context
|
102
98
|
|
103
99
|
more_opts = {
|
104
100
|
load_paths: ctx.config[:sass_assets_paths],
|
@@ -7,9 +7,24 @@ module SafeTemplate
|
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
10
|
-
class Slim::Template
|
10
|
+
class ::Slim::Template
|
11
11
|
include SafeTemplate
|
12
12
|
|
13
|
+
def initialize(file, line, opts, &block)
|
14
|
+
if opts.key?(:context)
|
15
|
+
context_hack = {
|
16
|
+
context: opts[:context]
|
17
|
+
}
|
18
|
+
|
19
|
+
::Slim::Embedded::SassEngine.disable_option_validator!
|
20
|
+
%w(sass scss markdown).each do |engine|
|
21
|
+
::Slim::Embedded.options[engine.to_sym] = context_hack
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
super
|
26
|
+
end
|
27
|
+
|
13
28
|
def precompiled_preamble(locals)
|
14
29
|
"__in_slim_template = true\n" << super
|
15
30
|
end
|
@@ -32,17 +47,6 @@ module Middleman
|
|
32
47
|
disable_escape: true
|
33
48
|
)
|
34
49
|
end
|
35
|
-
|
36
|
-
def after_configuration
|
37
|
-
context_hack = {
|
38
|
-
context: app.template_context_class.new(app)
|
39
|
-
}
|
40
|
-
|
41
|
-
::Slim::Embedded::SassEngine.disable_option_validator!
|
42
|
-
%w(sass scss markdown).each do |engine|
|
43
|
-
::Slim::Embedded.options[engine.to_sym] = context_hack
|
44
|
-
end
|
45
|
-
end
|
46
50
|
end
|
47
51
|
end
|
48
52
|
end
|