Permalink
Browse files

Allow _helpers.rb in blogs to provide custom Haml helpers. Document t…

…he provided ones. DRY up Haml rendering. Don't use OpenStruct for Haml context since it won't complain about methods that don't exist.
  • Loading branch information...
1 parent 15f0383 commit b9dea95f1ed100d5786d3cb580fcab968ab3b41f @henrik henrik committed Apr 16, 2009
Showing with 40 additions and 11 deletions.
  1. +12 −0 README.textile
  2. +18 −9 lib/jekyll/convertible.rb
  3. +8 −1 lib/jekyll/core_ext.rb
  4. +2 −1 lib/jekyll/site.rb
View
@@ -177,6 +177,18 @@ converted. Layouts don't need to.
Haml content is intentionally not filtered, so you can use any Ruby code.
+If you want to define methods you can call from your Haml files, create
+a _helpers.rb file in the root of your blog and put the methods there,
+inside a module named Helpers.
+
+Jekyll provides some helpers out of the box:
+
+ h(string)
+ HTML entity-escapes the input string.
+
+ link_to(text, url)
+ Creates a link to the URL with the linked text (or markup).
+
h3. Local Server
When previewing complex sites locally, simply opening the site in a web
View
@@ -59,6 +59,18 @@ def content_type
end
return 'unknown'
end
+
+ # Sets up a context for Haml and renders in it. The context has accessors
+ # matching the passed-in hash, e.g. "site", "page" and "content", and has
+ # helper modules mixed in.
+ #
+ # Returns String.
+ def render_haml_in_context(haml_engine, params={})
+ context = ClosedStruct.new(params)
+ context.extend(HamlHelpers)
+ context.extend(::Helpers) if defined?(::Helpers)
+ haml_engine.render(context)
+ end
# Add any necessary layouts to this convertible document
# +layouts+ is a Hash of {"name" => "layout"}
@@ -72,11 +84,10 @@ def do_layout(payload, layouts)
payload["content_type"] = self.content_type
if self.content_type == "haml"
- context = OpenStruct.new(:site => self.site, :page => OpenStruct.new(payload["page"]))
- context.extend(HamlHelpers)
-
self.transform
- self.content = self.content.render(context)
+ self.content = render_haml_in_context(self.content,
+ :site => self.site,
+ :page => ClosedStruct.new(payload["page"]))
else
self.content = Liquid::Template.parse(self.content).render(payload, info)
self.transform
@@ -91,12 +102,10 @@ def do_layout(payload, layouts)
payload = payload.deep_merge({"content" => self.output, "page" => layout.data})
if site.config['haml'] && layout.content.is_a?(Haml::Engine)
- context = OpenStruct.new(
- :page => OpenStruct.new(payload["page"]),
- :site => OpenStruct.new(payload["site"]),
+ self.output = render_haml_in_context(layout.content,
+ :site => ClosedStruct.new(payload["site"]),
+ :page => ClosedStruct.new(payload["page"]),
:content => payload["content"])
- context.extend(HamlHelpers)
- self.output = layout.content.render(context)
else
self.output = Liquid::Template.parse(layout.content).render(payload, info)
end
View
@@ -19,4 +19,11 @@ def deep_merge(hash)
target
end
-end
+end
+
+require 'ostruct'
+class ClosedStruct < OpenStruct
+ def method_missing(symbol, *args)
+ @table.has_key?(symbol) ? super : raise(NoMethodError, "undefined method `#{symbol}' for #{self}")
+ end
+end
View
@@ -50,8 +50,9 @@ def setup
if self.config['haml']
begin
require 'haml'
- require 'ostruct'
require 'jekyll/haml_helpers'
+ helpers = File.join(source, '_helpers.rb')
+ require helpers if File.exist?(helpers)
puts 'Enabled Haml'
rescue LoadError
puts 'You must have the haml gem installed first'

0 comments on commit b9dea95

Please sign in to comment.