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.
Files changed (93) hide show
  1. data/Gemfile +12 -0
  2. data/Gemfile.lock +27 -0
  3. data/LICENSE +20 -0
  4. data/README.markdown +107 -0
  5. data/Rakefile +45 -0
  6. data/VERSION.yml +5 -0
  7. data/bin/staticmatic +140 -0
  8. data/lib/staticmatic.rb +25 -0
  9. data/lib/staticmatic/base.rb +123 -0
  10. data/lib/staticmatic/compass.rb +5 -0
  11. data/lib/staticmatic/compass/app_integration.rb +18 -0
  12. data/lib/staticmatic/compass/configuration_defaults.rb +44 -0
  13. data/lib/staticmatic/compass/installer.rb +15 -0
  14. data/lib/staticmatic/configuration.rb +20 -0
  15. data/lib/staticmatic/deployers/aws-s3.rb +71 -0
  16. data/lib/staticmatic/deployers/config/amazon.yml +7 -0
  17. data/lib/staticmatic/error.rb +17 -0
  18. data/lib/staticmatic/helpers.rb +12 -0
  19. data/lib/staticmatic/helpers/assets_helper.rb +116 -0
  20. data/lib/staticmatic/helpers/current_path_helper.rb +22 -0
  21. data/lib/staticmatic/helpers/form_helper.rb +23 -0
  22. data/lib/staticmatic/helpers/render_helper.rb +13 -0
  23. data/lib/staticmatic/helpers/tag_helper.rb +35 -0
  24. data/lib/staticmatic/helpers/url_helper.rb +59 -0
  25. data/lib/staticmatic/mixins/build.rb +77 -0
  26. data/lib/staticmatic/mixins/helpers.rb +15 -0
  27. data/lib/staticmatic/mixins/render.rb +153 -0
  28. data/lib/staticmatic/mixins/rescue.rb +12 -0
  29. data/lib/staticmatic/mixins/server.rb +7 -0
  30. data/lib/staticmatic/mixins/setup.rb +16 -0
  31. data/lib/staticmatic/server.rb +86 -0
  32. data/lib/staticmatic/template_error.rb +44 -0
  33. data/lib/staticmatic/templates/rescues/default.haml +7 -0
  34. data/lib/staticmatic/templates/rescues/template.haml +18 -0
  35. data/spec/base_spec.rb +13 -0
  36. data/spec/compass_integration_spec.rb +27 -0
  37. data/spec/helpers/asset_helper_spec.rb +43 -0
  38. data/spec/helpers/custom_helper_spec.rb +18 -0
  39. data/spec/render_spec.rb +44 -0
  40. data/spec/rescue_spec.rb +36 -0
  41. data/spec/sandbox/test_site/config/compass.rb +1 -0
  42. data/spec/sandbox/test_site/config/site.rb +0 -0
  43. data/spec/sandbox/test_site/src/helpers/application_helper.rb +5 -0
  44. data/spec/sandbox/test_site/src/layouts/alternate_layout.haml +3 -0
  45. data/spec/sandbox/test_site/src/layouts/default.haml +7 -0
  46. data/spec/sandbox/test_site/src/layouts/projects.haml +1 -0
  47. data/spec/sandbox/test_site/src/pages/hello_world.erb +1 -0
  48. data/spec/sandbox/test_site/src/pages/index.haml +5 -0
  49. data/spec/sandbox/test_site/src/pages/layout_test.haml +2 -0
  50. data/spec/sandbox/test_site/src/pages/page_one.haml +3 -0
  51. data/spec/sandbox/test_site/src/pages/page_two.haml +2 -0
  52. data/spec/sandbox/test_site/src/pages/page_with_error.haml +5 -0
  53. data/spec/sandbox/test_site/src/pages/page_with_partial_error.haml +3 -0
  54. data/spec/sandbox/test_site/src/partials/menu.haml +1 -0
  55. data/spec/sandbox/test_site/src/partials/partial_with_error.haml +1 -0
  56. data/spec/sandbox/test_site/src/stylesheets/application.sass +5 -0
  57. data/spec/sandbox/test_site/src/stylesheets/css_with_error.sass +5 -0
  58. data/spec/sandbox/test_site/src/stylesheets/nested/a_nested_stylesheet.sass +0 -0
  59. data/spec/sandbox/test_site/src/stylesheets/partials/_forms.sass +2 -0
  60. data/spec/sandbox/test_site/src/stylesheets/sassy.scss +12 -0
  61. data/spec/server_spec.rb +11 -0
  62. data/spec/setup_spec.rb +22 -0
  63. data/spec/spec_helper.rb +14 -0
  64. data/spec/template_error_spec.rb +23 -0
  65. data/staticmatic.gemspec +158 -0
  66. data/website/Gemfile +1 -0
  67. data/website/config/site.rb +17 -0
  68. data/website/site/docs/compass_integration.html +70 -0
  69. data/website/site/docs/getting_started.html +49 -0
  70. data/website/site/docs/helpers.html +22 -0
  71. data/website/site/images/bycurve21.gif +0 -0
  72. data/website/site/images/curve21.jpg +0 -0
  73. data/website/site/images/homepage-build.jpg +0 -0
  74. data/website/site/images/homepage-previewing.jpg +0 -0
  75. data/website/site/images/homepage-templating.jpg +0 -0
  76. data/website/site/stylesheets/ie.css +5 -0
  77. data/website/site/stylesheets/print.css +372 -0
  78. data/website/site/stylesheets/screen.css +488 -0
  79. data/website/src/helpers/content_helper.rb +10 -0
  80. data/website/src/layouts/default.haml +15 -0
  81. data/website/src/pages/development.haml +9 -0
  82. data/website/src/pages/docs/_menu.haml +4 -0
  83. data/website/src/pages/docs/_requires_prerelease.haml +4 -0
  84. data/website/src/pages/docs/compass_integration.haml +54 -0
  85. data/website/src/pages/docs/getting_started.haml +31 -0
  86. data/website/src/pages/docs/helpers.haml +1 -0
  87. data/website/src/pages/index.haml +27 -0
  88. data/website/src/stylesheets/_base.scss +43 -0
  89. data/website/src/stylesheets/_defaults.scss +260 -0
  90. data/website/src/stylesheets/ie.scss +10 -0
  91. data/website/src/stylesheets/print.scss +33 -0
  92. data/website/src/stylesheets/screen.scss +73 -0
  93. 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,7 @@
1
+ module StaticMatic::ServerMixin
2
+ def preview
3
+ puts "StaticMatic Preview Server"
4
+ puts "Ctrl+C to exit"
5
+ StaticMatic::Server.start(self)
6
+ end
7
+ 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,7 @@
1
+ %h1= @exception.class.name
2
+
3
+ %p= @exception.message
4
+
5
+ %h2 Stack Trace
6
+
7
+ = @exception.backtrace.join("<br/>")
@@ -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/>")