staticmatic2 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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/>")
|