stefankroes / scribble

Scribble is a customer facing template language similar to Liquid build in Ruby
MIT License
122 stars 7 forks source link

Blocks in block? Rendering in methods? Compiled? #2

Closed iazel closed 9 years ago

iazel commented 9 years ago

Hello, I've just finished to read the README, and really liked it. I'm wondering: is it possible to use a block inside another block? If this is possible, template inheritance through layout block should be easily achieved and would be a big plus for this, already promising, template manager :)

I've seen your form example and wondering how do you implemented it, more specifically, you have to hard code the various formatting for creating a field text?
Stupid implementation to tell you what I mean:

def string(field, label)
   %Q(<label for="#{field}">#{label}</label><input type="text" name="#{field}">)
end

Or we can do something more extensible like:

def string(field, label)
   render('input_text', field: field, label: label)
end

Last, but not least: is the resulting code compiled or it's interpreted at each request?

Thank you, and good job!

stefankroes commented 9 years ago

It is very much possible to nest contexts (blocks, partials, layouts) which allows you to nest things like loops but also layouts. The next version of Sitebox.io will support custom layouts that are automatically loaded from a separate file (layout.html). It allows you to override the layout in subdirs but it could just as easily be build to nest layouts in subdirs.

Methods are evaluated while rendering the template and are not cached. The form method in Sitebox.io is implemented like what you describe above but it gathers all fields in an array before rendering them because it needs to do spam prevention and form validation.

The render method will not be available by default from a method implementation, you will have to inject a view context using registers. An instance of a class like this:

class ViewRenderer < ActionView::Base
  include Rails.application.routes.url_helpers
  include Rails.application.helpers

  def initialize
    super Rails.configuration.paths["app/views"].first
  end

  # Don't need this
  def protect_against_forgery?; false; end
end
stefankroes commented 9 years ago

Ta answer your last question: it is interpreted on each request. Or more specifically; the template is parsed and compiled into a Ruby AST on every initialization of Scribble::Template and the AST is evaluated on every call to #render.

iazel commented 9 years ago

Ok, thanks, I will scratch the code when I've spare time :P

stefankroes commented 9 years ago

np :+1: