staticmatic2 2.0.0
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.
- data/Gemfile +12 -0
- data/Gemfile.lock +27 -0
- data/LICENSE +20 -0
- data/README.markdown +107 -0
- data/Rakefile +45 -0
- data/VERSION.yml +5 -0
- data/bin/staticmatic +140 -0
- data/lib/staticmatic.rb +25 -0
- data/lib/staticmatic/base.rb +123 -0
- data/lib/staticmatic/compass.rb +5 -0
- data/lib/staticmatic/compass/app_integration.rb +18 -0
- data/lib/staticmatic/compass/configuration_defaults.rb +44 -0
- data/lib/staticmatic/compass/installer.rb +15 -0
- data/lib/staticmatic/configuration.rb +20 -0
- data/lib/staticmatic/deployers/aws-s3.rb +71 -0
- data/lib/staticmatic/deployers/config/amazon.yml +7 -0
- data/lib/staticmatic/error.rb +17 -0
- data/lib/staticmatic/helpers.rb +12 -0
- data/lib/staticmatic/helpers/assets_helper.rb +116 -0
- data/lib/staticmatic/helpers/current_path_helper.rb +22 -0
- data/lib/staticmatic/helpers/form_helper.rb +23 -0
- data/lib/staticmatic/helpers/render_helper.rb +13 -0
- data/lib/staticmatic/helpers/tag_helper.rb +35 -0
- data/lib/staticmatic/helpers/url_helper.rb +59 -0
- data/lib/staticmatic/mixins/build.rb +77 -0
- data/lib/staticmatic/mixins/helpers.rb +15 -0
- data/lib/staticmatic/mixins/render.rb +153 -0
- data/lib/staticmatic/mixins/rescue.rb +12 -0
- data/lib/staticmatic/mixins/server.rb +7 -0
- data/lib/staticmatic/mixins/setup.rb +16 -0
- data/lib/staticmatic/server.rb +86 -0
- data/lib/staticmatic/template_error.rb +44 -0
- data/lib/staticmatic/templates/rescues/default.haml +7 -0
- data/lib/staticmatic/templates/rescues/template.haml +18 -0
- data/spec/base_spec.rb +13 -0
- data/spec/compass_integration_spec.rb +27 -0
- data/spec/helpers/asset_helper_spec.rb +43 -0
- data/spec/helpers/custom_helper_spec.rb +18 -0
- data/spec/render_spec.rb +44 -0
- data/spec/rescue_spec.rb +36 -0
- data/spec/sandbox/test_site/config/compass.rb +1 -0
- data/spec/sandbox/test_site/config/site.rb +0 -0
- data/spec/sandbox/test_site/src/helpers/application_helper.rb +5 -0
- data/spec/sandbox/test_site/src/layouts/alternate_layout.haml +3 -0
- data/spec/sandbox/test_site/src/layouts/default.haml +7 -0
- data/spec/sandbox/test_site/src/layouts/projects.haml +1 -0
- data/spec/sandbox/test_site/src/pages/hello_world.erb +1 -0
- data/spec/sandbox/test_site/src/pages/index.haml +5 -0
- data/spec/sandbox/test_site/src/pages/layout_test.haml +2 -0
- data/spec/sandbox/test_site/src/pages/page_one.haml +3 -0
- data/spec/sandbox/test_site/src/pages/page_two.haml +2 -0
- data/spec/sandbox/test_site/src/pages/page_with_error.haml +5 -0
- data/spec/sandbox/test_site/src/pages/page_with_partial_error.haml +3 -0
- data/spec/sandbox/test_site/src/partials/menu.haml +1 -0
- data/spec/sandbox/test_site/src/partials/partial_with_error.haml +1 -0
- data/spec/sandbox/test_site/src/stylesheets/application.sass +5 -0
- data/spec/sandbox/test_site/src/stylesheets/css_with_error.sass +5 -0
- data/spec/sandbox/test_site/src/stylesheets/nested/a_nested_stylesheet.sass +0 -0
- data/spec/sandbox/test_site/src/stylesheets/partials/_forms.sass +2 -0
- data/spec/sandbox/test_site/src/stylesheets/sassy.scss +12 -0
- data/spec/server_spec.rb +11 -0
- data/spec/setup_spec.rb +22 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/template_error_spec.rb +23 -0
- data/staticmatic.gemspec +158 -0
- data/website/Gemfile +1 -0
- data/website/config/site.rb +17 -0
- data/website/site/docs/compass_integration.html +70 -0
- data/website/site/docs/getting_started.html +49 -0
- data/website/site/docs/helpers.html +22 -0
- data/website/site/images/bycurve21.gif +0 -0
- data/website/site/images/curve21.jpg +0 -0
- data/website/site/images/homepage-build.jpg +0 -0
- data/website/site/images/homepage-previewing.jpg +0 -0
- data/website/site/images/homepage-templating.jpg +0 -0
- data/website/site/stylesheets/ie.css +5 -0
- data/website/site/stylesheets/print.css +372 -0
- data/website/site/stylesheets/screen.css +488 -0
- data/website/src/helpers/content_helper.rb +10 -0
- data/website/src/layouts/default.haml +15 -0
- data/website/src/pages/development.haml +9 -0
- data/website/src/pages/docs/_menu.haml +4 -0
- data/website/src/pages/docs/_requires_prerelease.haml +4 -0
- data/website/src/pages/docs/compass_integration.haml +54 -0
- data/website/src/pages/docs/getting_started.haml +31 -0
- data/website/src/pages/docs/helpers.haml +1 -0
- data/website/src/pages/index.haml +27 -0
- data/website/src/stylesheets/_base.scss +43 -0
- data/website/src/stylesheets/_defaults.scss +260 -0
- data/website/src/stylesheets/ie.scss +10 -0
- data/website/src/stylesheets/print.scss +33 -0
- data/website/src/stylesheets/screen.scss +73 -0
- metadata +238 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
module StaticMatic::BuildMixin
|
|
2
|
+
|
|
3
|
+
def build
|
|
4
|
+
build_css
|
|
5
|
+
build_js
|
|
6
|
+
build_html
|
|
7
|
+
copy_images
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# Build HTML from the source files
|
|
11
|
+
def build_html
|
|
12
|
+
src_file_paths('haml').each do |path|
|
|
13
|
+
file_dir, template = source_template_from_path(path.sub(/^#{@src_dir}/, ''))
|
|
14
|
+
save_page(File.join(file_dir, template), generate_html_with_layout(template, file_dir))
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Build CSS from the source files
|
|
19
|
+
def build_css
|
|
20
|
+
src_file_paths('sass','scss').each do |path|
|
|
21
|
+
file_dir, template = source_template_from_path(path.sub(/^#{@src_dir}/, ''))
|
|
22
|
+
|
|
23
|
+
if !template.match(/(^|\/)\_/)
|
|
24
|
+
save_stylesheet(File.join(file_dir, template), generate_css(template, file_dir))
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def build_js
|
|
30
|
+
coffee_found = ENV['PATH'].split(':').inject(false) { |found, folder| found |= File.exists?("#{folder}/coffee") }
|
|
31
|
+
if coffee_found
|
|
32
|
+
src_file_paths('coffee').each do |path|
|
|
33
|
+
file_dir, template = source_template_from_path(path.sub(/^#{@src_dir}/, ''))
|
|
34
|
+
save_javascript(File.join(file_dir, template), generate_js(template, file_dir))
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
# copy normal javascript files over
|
|
38
|
+
src_file_paths('js').each do |path|
|
|
39
|
+
file_dir, template = source_template_from_path(path.sub(/^#{@src_dir}/, ''))
|
|
40
|
+
copy_file(path, File.join(@site_dir, file_dir, "#{template}.js"))
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def copy_images
|
|
45
|
+
src_file_paths(*%w{gif jpg jpef png tiff}).each do |path|
|
|
46
|
+
file_dir, file_name = File.split(path.sub(/^#{@src_dir}/, ''))
|
|
47
|
+
copy_file(path, File.join(@site_dir, 'images', file_dir, file_name))
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def copy_file(from, to)
|
|
52
|
+
FileUtils.mkdir_p(File.dirname(to))
|
|
53
|
+
FileUtils.cp(from, to)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def save_page(filename, content)
|
|
57
|
+
generate_site_file(filename, 'html', content)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def save_stylesheet(filename, content)
|
|
61
|
+
generate_site_file(filename, 'css', content)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def save_javascript(filename, content)
|
|
65
|
+
generate_site_file(filename, 'js', content)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def generate_site_file(filename, extension, content)
|
|
69
|
+
path = File.join(@site_dir,"#{filename}.#{extension}")
|
|
70
|
+
FileUtils.mkdir_p(File.dirname(path))
|
|
71
|
+
File.open(path, 'w+') do |f|
|
|
72
|
+
f << content
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
puts "created #{path}"
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module StaticMatic::HelpersMixin
|
|
2
|
+
# Loads any helpers present in the helpers dir and mixes them into the template helpers
|
|
3
|
+
def load_helpers
|
|
4
|
+
|
|
5
|
+
Dir["#{@src_dir}/_helpers/**/*_helper.rb"].each do |helper|
|
|
6
|
+
load_helper(helper)
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def load_helper(helper)
|
|
11
|
+
load helper
|
|
12
|
+
module_name = File.basename(helper, '.rb').gsub(/(^|\_)./) { |c| c.upcase }.gsub(/\_/, '')
|
|
13
|
+
Haml::Helpers.class_eval("include #{module_name}")
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
module StaticMatic::RenderMixin
|
|
2
|
+
|
|
3
|
+
# clear all scope variables except @staticmatic
|
|
4
|
+
def clear_template_variables!
|
|
5
|
+
|
|
6
|
+
@scope.instance_variables.each do |var|
|
|
7
|
+
@scope.instance_variable_set(var, nil) unless var == '@staticmatic' || var == :@staticmatic
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def source_for_layout
|
|
12
|
+
if layout_exists?(determine_layout)
|
|
13
|
+
File.read(full_layout_path(determine_layout))
|
|
14
|
+
else
|
|
15
|
+
raise StaticMatic::Error.new("", full_layout_path(determine_layout), "Layout not found")
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Generate html from source file:
|
|
20
|
+
# generate_html("index")
|
|
21
|
+
def generate_html(source_file, source_dir = '')
|
|
22
|
+
full_file_path = File.join(@src_dir, source_dir, "#{source_file}.haml")
|
|
23
|
+
|
|
24
|
+
begin
|
|
25
|
+
|
|
26
|
+
html = generate_html_from_template_source(File.read(full_file_path))
|
|
27
|
+
rescue StaticMatic::TemplateError => e
|
|
28
|
+
raise e # re-raise inline errors
|
|
29
|
+
rescue Exception => e
|
|
30
|
+
raise StaticMatic::TemplateError.new(full_file_path, e)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
html
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def generate_html_with_layout(source, source_dir = '')
|
|
37
|
+
@current_page = File.join(source_dir, "#{source}.html")
|
|
38
|
+
@current_file_stack.unshift(File.join(source_dir, "#{source}.haml"))
|
|
39
|
+
begin
|
|
40
|
+
template_content = generate_html(source, source_dir)
|
|
41
|
+
generate_html_from_template_source(source_for_layout) { template_content }
|
|
42
|
+
rescue Exception => e
|
|
43
|
+
render_rescue_from_error(e)
|
|
44
|
+
ensure
|
|
45
|
+
clear_template_variables!
|
|
46
|
+
@current_page = nil
|
|
47
|
+
@current_file_stack.shift
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def generate_partial(name, options = {})
|
|
52
|
+
partial_dir, partial_name = File.dirname(self.current_file), name # default relative to current file
|
|
53
|
+
partial_dir, partial_name = File.split(name) if name.index('/') # contains a path so it's absolute from src/pages dir
|
|
54
|
+
partial_type = partial_name[/(\.haml|\.html)$/]
|
|
55
|
+
|
|
56
|
+
partial_name = "_#{partial_name}"
|
|
57
|
+
partial_name += ".haml" unless partial_type
|
|
58
|
+
|
|
59
|
+
partial_path = File.join(@src_dir, partial_dir, partial_name)
|
|
60
|
+
unless File.exists?(partial_path)
|
|
61
|
+
# couldn't find it in the pages subdirectory tree so try old way (ignoring the path)
|
|
62
|
+
partial_dir = '_partials'
|
|
63
|
+
partial_name = "#{File.basename(name)}"
|
|
64
|
+
partial_name += ".haml" unless partial_type
|
|
65
|
+
partial_path = File.join(@src_dir, partial_dir, partial_name)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
if File.exists?(partial_path)
|
|
69
|
+
partial_rel_path = "/#{partial_dir}/#{partial_name}".gsub(/\/+/, '/')
|
|
70
|
+
@current_file_stack.unshift(partial_rel_path)
|
|
71
|
+
begin
|
|
72
|
+
if partial_type == '.html'
|
|
73
|
+
File.read(partial_path)
|
|
74
|
+
else
|
|
75
|
+
generate_html_from_template_source(File.read(partial_path), options)
|
|
76
|
+
end
|
|
77
|
+
rescue Exception => e
|
|
78
|
+
raise StaticMatic::TemplateError.new(partial_path, e)
|
|
79
|
+
ensure
|
|
80
|
+
@current_file_stack.shift
|
|
81
|
+
end
|
|
82
|
+
else
|
|
83
|
+
raise StaticMatic::Error.new("", name, "Partial not found")
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def generate_css(source, source_dir = '')
|
|
88
|
+
full_file_path = Dir[File.join(@src_dir, source_dir, "#{source}.{sass,scss}")].first
|
|
89
|
+
|
|
90
|
+
if full_file_path && File.exist?(full_file_path)
|
|
91
|
+
begin
|
|
92
|
+
sass_options = { :load_paths => [ @src_dir ] }.merge(self.configuration.sass_options)
|
|
93
|
+
|
|
94
|
+
if File.extname(full_file_path) == ".scss"
|
|
95
|
+
sass_options[:syntax] = :scss
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
stylesheet = Sass::Engine.new(File.read(full_file_path), sass_options)
|
|
99
|
+
stylesheet.to_css
|
|
100
|
+
rescue Exception => e
|
|
101
|
+
render_rescue_from_error(StaticMatic::TemplateError.new(full_file_path, e))
|
|
102
|
+
end
|
|
103
|
+
else
|
|
104
|
+
raise StaticMatic::Error.new("", source, "Stylesheet not found")
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def generate_js(source, source_dir = '')
|
|
109
|
+
full_file_path = File.join(@src_dir, source_dir, "#{source}.coffee")
|
|
110
|
+
|
|
111
|
+
coffee_options = "#{self.configuration.coffee_options} -p"
|
|
112
|
+
javascript = `coffee #{coffee_options} #{full_file_path}`
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Generates html from the passed source string
|
|
116
|
+
#
|
|
117
|
+
# generate_html_from_template_source("%h1 Welcome to My Site") -> "<h1>Welcome to My Site</h1>"
|
|
118
|
+
#
|
|
119
|
+
# Pass a block containing a string to yield within in the passed source:
|
|
120
|
+
#
|
|
121
|
+
# generate_html_from_template_source("content:\n= yield") { "blah" } -> "content: blah"
|
|
122
|
+
#
|
|
123
|
+
def generate_html_from_template_source(source, options = {})
|
|
124
|
+
html = Haml::Engine.new(source, self.configuration.haml_options.merge(options))
|
|
125
|
+
locals = options[:locals] || {}
|
|
126
|
+
html.render(@scope, locals) { yield }
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def determine_layout(dir = '')
|
|
130
|
+
layout_name ||= @default_layout
|
|
131
|
+
|
|
132
|
+
if @scope.instance_variable_get("@layout")
|
|
133
|
+
layout_name = @scope.instance_variable_get("@layout")
|
|
134
|
+
elsif dir
|
|
135
|
+
dirs = dir.split("/")
|
|
136
|
+
dir_layout_name = dirs[1]
|
|
137
|
+
|
|
138
|
+
if layout_exists?(dir_layout_name)
|
|
139
|
+
layout_name = dir_layout_name
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
layout_name
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# Returns a raw template name from a source file path:
|
|
147
|
+
# source_template_from_path("/path/to/site/src/stylesheets/application.sass") -> "application"
|
|
148
|
+
def source_template_from_path(path)
|
|
149
|
+
file_dir, file_name = File.split(path)
|
|
150
|
+
file_name.chomp!(File.extname(file_name))
|
|
151
|
+
[ file_dir, file_name ]
|
|
152
|
+
end
|
|
153
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
module StaticMatic::RescueMixin
|
|
2
|
+
# Pass back an error template for the given exception
|
|
3
|
+
def render_rescue_from_error(exception)
|
|
4
|
+
rescue_template = (exception.is_a?(StaticMatic::TemplateError)) ? "template" : "default"
|
|
5
|
+
|
|
6
|
+
error_template_path = File.expand_path(File.dirname(__FILE__) + "/../templates/rescues/#{rescue_template}.haml")
|
|
7
|
+
|
|
8
|
+
@scope.instance_variable_set("@exception", exception)
|
|
9
|
+
|
|
10
|
+
generate_html_from_template_source(File.read(error_template_path))
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module StaticMatic::SetupMixin
|
|
2
|
+
|
|
3
|
+
def setup
|
|
4
|
+
Dir.mkdir(@base_dir) unless File.exists?(@base_dir)
|
|
5
|
+
|
|
6
|
+
Dir[File.join(File.dirname(__FILE__), "..", "templates", "project", "*")].each do |template|
|
|
7
|
+
begin
|
|
8
|
+
FileUtils.cp_r(template, @base_dir)
|
|
9
|
+
rescue Errno::EEXIST
|
|
10
|
+
# ignore - template exists
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
puts "Done"
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
module StaticMatic
|
|
2
|
+
class Server
|
|
3
|
+
def initialize(staticmatic, default = nil)
|
|
4
|
+
@files = default || Rack::File.new(staticmatic.src_dir)
|
|
5
|
+
@staticmatic = staticmatic
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def call(env)
|
|
11
|
+
@staticmatic.load_helpers
|
|
12
|
+
path_info = env["PATH_INFO"]
|
|
13
|
+
|
|
14
|
+
file_dir, file_name, file_ext = expand_path(path_info)
|
|
15
|
+
|
|
16
|
+
file_dir = CGI::unescape(file_dir)
|
|
17
|
+
file_name = CGI::unescape(file_name)
|
|
18
|
+
|
|
19
|
+
unless file_ext && ["html", "css", "js"].include?(file_ext) &&
|
|
20
|
+
@staticmatic.template_exists?(file_name, file_ext, file_dir) &&
|
|
21
|
+
File.basename(file_name) !~ /^\_/
|
|
22
|
+
return @files.call(env)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
res = Rack::Response.new
|
|
26
|
+
res.header["Content-Type"] = "text/#{file_ext}"
|
|
27
|
+
|
|
28
|
+
begin
|
|
29
|
+
if file_ext == "css"
|
|
30
|
+
res.write @staticmatic.generate_css(file_name, file_dir)
|
|
31
|
+
elsif file_ext == "js"
|
|
32
|
+
res.header["Content-Type"] = "text/javascript"
|
|
33
|
+
res.write @staticmatic.generate_js(file_name, file_dir)
|
|
34
|
+
else
|
|
35
|
+
res.write @staticmatic.generate_html_with_layout(file_name, file_dir)
|
|
36
|
+
end
|
|
37
|
+
rescue StaticMatic::Error => e
|
|
38
|
+
res.write e.message
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
res.finish
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Starts the StaticMatic preview server
|
|
45
|
+
def self.start(staticmatic)
|
|
46
|
+
[ 'INT', 'TERM' ].each do |signal|
|
|
47
|
+
Signal.trap(signal) do
|
|
48
|
+
puts
|
|
49
|
+
puts "Exiting"
|
|
50
|
+
exit!(0)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
port = staticmatic.configuration.preview_server_port || 3000
|
|
54
|
+
|
|
55
|
+
host = staticmatic.configuration.preview_server_host || ""
|
|
56
|
+
|
|
57
|
+
app = Rack::Builder.new do
|
|
58
|
+
use Rack::ShowExceptions
|
|
59
|
+
run StaticMatic::Server.new(staticmatic)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
Rack::Handler::WEBrick.run(app, :Port => port, :Host => host)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
private
|
|
66
|
+
|
|
67
|
+
def expand_path(path_info)
|
|
68
|
+
dirname, basename = File.split(path_info)
|
|
69
|
+
|
|
70
|
+
extname = File.extname(path_info).sub(/^\./, '')
|
|
71
|
+
filename = basename.chomp(".#{extname}")
|
|
72
|
+
|
|
73
|
+
if extname.empty?
|
|
74
|
+
dir = File.join(dirname, filename)
|
|
75
|
+
is_dir = path_info[-1, 1] == '/'
|
|
76
|
+
if is_dir
|
|
77
|
+
dirname = dir
|
|
78
|
+
filename = 'index'
|
|
79
|
+
end
|
|
80
|
+
extname = 'html'
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
[ dirname, filename, extname ]
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
class StaticMatic::TemplateError < StandardError
|
|
2
|
+
SOURCE_CODE_RADIUS = 3
|
|
3
|
+
|
|
4
|
+
attr_reader :original_exception, :backtrace
|
|
5
|
+
|
|
6
|
+
def initialize(template, original_exception)
|
|
7
|
+
@template, @original_exception = template, original_exception
|
|
8
|
+
@backtrace = original_exception.backtrace
|
|
9
|
+
|
|
10
|
+
if template
|
|
11
|
+
@source = File.read(template)
|
|
12
|
+
else
|
|
13
|
+
@source = ""
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# TODO: Replace 'haml|sass' with any registered engines
|
|
18
|
+
def line_number
|
|
19
|
+
@line_number ||= $2 if backtrace.find { |line| line =~ /\((haml|sass|scss)\)\:(\d+)/ }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def filename
|
|
23
|
+
@template
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def source_extract(indentation = 0)
|
|
27
|
+
return "" unless num = line_number
|
|
28
|
+
num = num.to_i
|
|
29
|
+
|
|
30
|
+
source_code = @source.split("\n")
|
|
31
|
+
|
|
32
|
+
start_on_line = [ num - SOURCE_CODE_RADIUS - 1, 0 ].max
|
|
33
|
+
end_on_line = [ num + SOURCE_CODE_RADIUS - 1, source_code.length].min
|
|
34
|
+
|
|
35
|
+
indent = ' ' * indentation
|
|
36
|
+
line_counter = start_on_line
|
|
37
|
+
return unless source_code = source_code[start_on_line..end_on_line]
|
|
38
|
+
|
|
39
|
+
source_code.collect do |line|
|
|
40
|
+
line_counter += 1
|
|
41
|
+
"#{indent}#{line_counter}: #{line}\n"
|
|
42
|
+
end.to_s
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
%html
|
|
2
|
+
%head
|
|
3
|
+
%style{:type => "text/css"}
|
|
4
|
+
body { font-family: helvetica, verdana, arial; font-size: 10pt;}
|
|
5
|
+
%body
|
|
6
|
+
%h1
|
|
7
|
+
= @exception.class.name
|
|
8
|
+
in
|
|
9
|
+
= @exception.filename
|
|
10
|
+
|
|
11
|
+
%p= @exception.original_exception.message
|
|
12
|
+
|
|
13
|
+
= @exception.source_extract.gsub(/\n/, "<br/>")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
%h2 Backtrace
|
|
17
|
+
|
|
18
|
+
= @exception.backtrace.join("<br/>")
|