Skip to content
Browse files

More work

  • Loading branch information...
1 parent f50ec06 commit c66b35bf2caa2f2adbaa4931fd9bc4b55520be80 @winton committed Mar 15, 2011
View
114 README.md
@@ -41,14 +41,14 @@ Stasis uses [Tilt](https://github.com/rtomayko/tilt) to support the following te
Example
-------
-Our [spec project](https://github.com/winton/stasis/tree/master/spec/fixtures/project) implements all the features below.
+The [spec project](https://github.com/winton/stasis/tree/master/spec/fixtures/project) implements all of the features in this README.
Get Started
-----------
-Create a directory for your project and a markup file:
+Create a directory for your project, and within that directory, a markup file:
-### view.erb
+### view.html.erb
Welcome <%= '!' * 3 %>
@@ -63,7 +63,11 @@ You now have a `public` directory with rendered markup:
public/
view.html
- view.erb
+ view.html.erb
+
+If the file extension is a supported markup file, it renders into `public`.
+
+If the file extension is unsupported, it copies into `public`.
Controllers
-----------
@@ -88,58 +92,73 @@ Define `before` and `after` render callbacks within your controller:
# Call before any file renders
before do
- @title = 'Default Title'
+ @what_is_rendering = "any file"
end
+
+ # Call before any ERB file renders
- # Call only before view.erb renders
+ before /.*erb/ do
+ @what_is_rendering = "ERB file"
+ end
- before 'view.erb' do
- @title = 'My Site'
+ # Call only before view.html.erb renders
+
+ before 'view.html.erb' do
+ @what_is_rendering = "the view"
end
-### view.erb
+### view.html.erb
- Welcome to <%= @title %>!
+ <%= @what_is_rendering %>
Change the Destination
----------------------
-Let's say we want `view.erb` to be our front page:
+Let's say we want `view.html.erb` to be our front page:
### controller.rb
- before 'view.erb' do
+ destination 'view.html.erb' => '/index.html'
+
+ # or
+
+ before 'view.html.erb' do
@destination = '/index.html'
end
+Ignore
+------
+
+Sometimes you will want to ignore certain files entirely (no render, no copy).
+
+For example, ignore file names with an underscore at the beginning:
+
+### controller.rb
+
+ ignore /_.*/
+
Layouts
-------
Create the layout markup:
-### layout.erb
+### layout.html.erb
<html>
- <head>
- <title><%= @title %></title>
- </head>
<body><%= yield %></body>
</html>
### controller.rb
- before 'view.erb' do
- @layout = 'layout.erb'
- @title = 'My Site'
- end
+ layout 'view.html.erb' => 'layout.html.erb'
- before 'layout.erb' do
- @destination = nil
+ # or
+
+ before 'view.html.erb' do
+ @layout = 'layout.html.erb'
end
-We want `view.erb` to use the layout, so we set `@layout = 'layout.erb'`.
-
-We do not want a `public/layout.html` file, so we set `@destination = nil`.
+Layout files are automatically ignored (don't want to render a `layout.html` file).
Helpers
-------
@@ -154,18 +173,46 @@ Define helper methods within your controllers.
end
end
-### layout.erb
+### layout.html.erb
+
+ <% if active?('view.html.erb') %>
+ Rendering view.html.erb
+ <% end -%>
+
+Priority
+--------
+
+You may want some files to render or copy before others:
+
+### controller.rb
+
+ priority 'view.html.erb' => 1, /.*css/ => 2, /.*js/ => 2
+
+The default priority is `0`.
+
+Summary
+-------
+
+Use the following methods in your controllers:
+
+* `after`
+* `before`
+* `destination`
+* `ignore`
+* `layout`
+* `priority`
+
+Use the following methods within a callback, helper, or view:
- <%= active?('view.erb') %>
+* `render`
-Class Variables
----------------
+Use the following class variables in your callbacks, helpers, or views:
-To summarize, the following class variables have a special purpose in a Stasis project:
+* `@destination`
+* `@layout`
+* `@source`
-* `@destination` - Get/set the destination path within `public/`
-* `@layout` - Get/set a file path to use as the layout
-* `@source` - Get/set the file path that is being rendered
+Only alter these class variables from a `before` callback.
Continuous Rendering
--------------------
@@ -188,5 +235,6 @@ In web server mode, Stasis continuously renders (`-c`).
Other Topics:
-------------
+* [Asset Packaging](https://github.com/winton/stasis/wiki/Asset-Packaging)
* [Callback Execution Order](https://github.com/winton/stasis/wiki/Callback-Execution-Order).
* [Run Stasis Programmatically](https://github.com/winton/stasis/wiki/Run-Stasis-Programmatically)
View
135 lib/stasis.rb
@@ -16,46 +16,67 @@ class Stasis
def initialize(root)
@root = root
@controllers = Dir["#{root}/**/controller.rb"].inject({}) do |hash, path|
- context = Context::Controller.new
- context.instance_eval File.read(path), path
- hash[File.dirname(path)] = context
+ context = Context::Controller.new path, root
+ hash[context._stasis[:dir]] = context
hash
end
end
def generate(*paths)
- paths.collect! { |p| "#{root}/#{p}" }
- Dir[*paths].each do |path|
- rel_path = path[root.length+1..-1]
+ paths = paths.collect { |p| Dir["#{root}/#{p}"] }.flatten
+ priorities = @controllers.values.inject([]) do |array, context|
+ array += context._stasis[:priority] || []
+ end
+ priorities.sort! { |a, b| b[1] <=> a[1] }
+ priorities = priorities.inject({}) do |hash, (path_or_regexp, priority)|
+ paths.each do |path|
+ if path_or_regexp.is_a?(::Regexp) && path =~ path_or_regexp
+ hash[path] = priority
+ elsif path == path_or_regexp
+ hash[path] = priority
+ end
+ end
+ hash
+ end
+ priorities.merge! (paths - priorities.keys).inject({}) { |hash, path|
+ hash[path] = 0
+ hash
+ }
+ priorities = priorities.to_a.sort { |a, b| b[1] <=> a[1] }
+ paths = priorities.collect { |(path, priority)| path }
+ paths -= @controllers.values.inject([]) { |array, context|
+ array += context._stasis[:ignore] || []
+ }
+ paths.each do |path|
next unless File.file?(path)
next unless Tilt.mappings.keys.include?(File.extname(path)[1..-1])
+ rel_path = path[root.length+1..-1]
context = Context::Render.new rel_path
- trigger :helpers, context, path, rel_path
- trigger :before, context, path, rel_path
- next if context.ignore
+ trigger :helpers, context, path
+ trigger :before, context, path
+ next unless context.destination
template = Tilt.new path
view = template.render(context)
- trigger :after, context, path, rel_path
+ trigger :after, context, path
if context.layout
layout_path = "#{root}/#{context.layout}"
- trigger :before, context, layout_path, context.layout
+ trigger :before, context, layout_path
template = Tilt.new layout_path
layout = template.render(context) { view }
- trigger :after, context, layout_path, context.layout
+ trigger :after, context, layout_path
end
puts view.inspect
puts layout.inspect
end
end
- def trigger(type, context, path, rel_path)
+ def trigger(type, context, path)
dir = File.dirname path
- begin
+ while dir != File.expand_path('../', root) && dir != '/'
callbacks = controllers[dir]
if callbacks
blocks = callbacks.send(type, nil)
- blocks += callbacks.send(type, rel_path)
- blocks += callbacks.send(type, File.basename(rel_path))
+ blocks += callbacks.send(type, path)
blocks.each do |block|
if type == :helpers
context.class.class_eval &block
@@ -65,48 +86,80 @@ def trigger(type, context, path, rel_path)
end
end
dir = File.expand_path('../', dir)
- end while dir != root && dir != '/'
+ end
end
class Context
class Controller
- def after(view=nil, &block)
- @after ||= {}
- @after[view] ||= []
- if block
- @after[view] << block
- else
- @after[view]
- end
+ attr_reader :_stasis
+
+ def initialize(path, root)
+ dir = File.dirname path
+ rel_dir = File.dirname(path)[root.length+1..-1]
+ @_stasis = {
+ :dir => dir,
+ :path => path,
+ :rel_dir => rel_dir,
+ :resolve => lambda { |view|
+ if view.nil?
+ nil
+ elsif view.is_a?(Regexp)
+ view
+ elsif File.file?(p = "#{root}#{rel_dir}/#{view}")
+ p
+ elsif File.file?(p = "#{root}/#{view}")
+ p
+ else
+ false
+ end
+ },
+ :root => root
+ }
+ instance_eval File.read(path), path
+ end
+
+ %w(after before helpers).each do |type|
+ class_eval <<-EVAL
+ def #{type}(view=nil, &block)
+ @_stasis[:#{type}] ||= {}
+ if block
+ view = @_stasis[:resolve].call view
+ return [] if view == false
+ @_stasis[:#{type}][view] ||= []
+ @_stasis[:#{type}][view] << block
+ else
+ @_stasis[:#{type}][view] || []
+ end
+ end
+ EVAL
end
- def before(view=nil, &block)
- @before ||= {}
- @before[view] ||= []
- if block
- @before[view] << block
- else
- @before[view]
+ def ignore(*array)
+ @_stasis[:ignore] ||= []
+ @_stasis[:ignore] += array.collect do |path|
+ path = @_stasis[:resolve].call path
+ path ? path : nil
end
+ @_stasis[:ignore].compact!
end
- def helpers(view=nil, &block)
- @helpers ||= {}
- @helpers[view] ||= []
- if block
- @helpers[view] << block
- else
- @helpers[view]
+ def priority(hash)
+ @_stasis[:priority] ||= []
+ @_stasis[:priority] += hash.to_a.collect do |pair|
+ pair[0] = @_stasis[:resolve].call pair[0]
+ pair[0] ? pair : nil
end
+ @_stasis[:priority].compact!
end
end
class Render
- attr_reader :ignore, :path, :layout, :view
+ attr_reader :destination, :layout, :source
def initialize(rel_path)
- @view = rel_path
+ @destination = rel_path.split('.')[0..-2].join('.')
+ @source = rel_path
end
end
end
View
9 spec/fixtures/project/controller.rb
@@ -1,9 +1,8 @@
-before 'layout.erb' do
- @ignore = true
-end
+ignore 'layout.html.erb'
+priority /.*erb/ => 1
-before 'view.erb' do
- @layout = 'layout.erb'
+before 'view.html.erb' do
+ @layout = 'layout.html.erb'
@title = 'My Site'
end
View
0 spec/fixtures/project/layout.erb → spec/fixtures/project/layout.html.erb
File renamed without changes.
View
0 spec/fixtures/project/view.erb → spec/fixtures/project/view.html.erb
File renamed without changes.

0 comments on commit c66b35b

Please sign in to comment.
Something went wrong with that request. Please try again.