Code Monkey home page Code Monkey logo

erbse's Introduction

Erbse

An updated version of Erubis.

Erbse compiles an ERB string to a string of Ruby.

API

The API is one public method.

Erbse::Engine.new.call("<% ... %>") #=> string of compiled ruby.

The returned string can then be evaluated in a certain context.

Output Buffers

Erbse does not use instance variables as output buffer, only local variables.

Tag Behavior
<% %> Executes the code but does not output anything.
<% .. do %> Executes the code but does not output anything. In the block, output is written to the current buffer.
<%= %> Executes the code, outputs to current buffer.
<%= .. do %> Executes the code and appends returned value to the current buffer. In the block, output is written to a new buffer that is returned when yielding.
<%@ .. do %> Executes the code but does not output anything. In the block, output is written to a new buffer that is returned when yielding.

Block Yielding

Erbse supports blocks ร  la Rails.

You may pass any mix of text/ERB via blocks to Ruby methods.

<%= form do %>
  <em>Please fill out all fields!</em>
  <%= input :email %>
  <button type="submit">
<% end %>

Here, the form method receives a block of compiled Ruby.

When yielded, the block simply returns its evaluated content as a string. It's your job to assign it to an output buffer, no instance variables are used.

def form(&block)
  content = yield
  "<form>#{content}</form>"
end

Usually, returning the content from the helper will be sufficient.

However, you can totally pass that block to a completely different object and yield it there. Since there's no global state as in ERB, this will work.

Capture

With the <%= helper do %> tag, block content is assigned to a new output buffer and the result of helper rendered.

To capture the block without outputting anything, use the <%@ %> tag. This will still use a new output buffer for the block, but not output anything.

<%@ content = capture do %>
  Whatever
<% end %>

<%= content %>

The capture method will receive a block, what you do with it is up to you. It would usually simply yield the block.

def capture(&block)
  yield
end

Removed Features

Erbse does not support any tags other than <% %>, <%= %> and <%@ %>. Tags such as <%% %>, <%== %>, <%- %> or <% -%> will be reduced to the supported tags.

TODO

The parser code got drastically reduced and might be missing essential features. Please report compiled syntax errors.

  • Block comments
  • Add newlines in compiled Ruby.

Planned

Block inheritance.

<h1><%= title %></h1>

<% fragment :subheader do %>
  Or: <%= subheader %>
<% end %>

This fragment could then be overridden.

Feel free to contribute!!!

Users

Erbse is the ERB engine in Cells.

License

MIT License

Contributors

Authors

  • Copyright 2015 Nick Sutterer [email protected]
  • Copyright 2006-2011 makoto kuwata <kwa(at)kuwata-lab.com>

erbse's People

Contributors

aiomaster avatar apotonick avatar fsateler avatar scharrels avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

erbse's Issues

Inline conditionals not supported

Erbse fails with inline conditionals such as:

<%= f.input :captain_hired if boat.captain_available? && !boat.captain_mandatory? %>

This will produce an obscure error like the following:

SyntaxError:
  app/concepts/boat_booker/views/show/_form.erb:5: syntax error, unexpected keyword_else, expecting keyword_end
  ; _buf << ("        </div>\n      ".freeze);  else ; 
                                                   ^
  app/concepts/boat_booker/views/show/_form.erb:12: syntax error, unexpected keyword_end, expecting end-of-input
  end;end;end;end
             ^

Newline after evaluation block is ignored

With a template like:

abc
<%= 'foo' %>
def

I expected result

abc
foo
def

with erbse 0.1.3, I end up with a missing newline:

irb(main):004:0> puts Erbse::Engine.new.call("abc\n<%= 'foo' %>\ndef")
_buf = []; _buf << ("abc\n".freeze); _buf << ( 'foo' );
; _buf << ("def".freeze); _buf = _buf.join("".freeze)

# _buf == "abc\nfoodef"

incorrect postfix conditionals evaluation

what <%= 'ever' if true %>

evaluates to an empty string

> eval Erbse::Engine.new.call("what <%= 'ever' if false %>")
 => ""
> Erbse::Parser.new.call("what <%= 'ever' if true %>")
 => [:multi]

==========

<% [].each do %>
  <% next if true %>
<% end %>

produces incorrect ruby syntax

> eval Erbse::Engine.new.call("<% [].each do %>\n<% next if true %>\n<% end %>")
SyntaxError: (eval):3: syntax error, unexpected keyword_end, expecting end-of-input
; end; _buf = _buf.join("".freeze)
     ^
        from (irb):8:in `eval'
        from (irb):8
        from /home/roma/.rvm/rubies/ruby-2.3.3/bin/irb:11:in `<main>'
> Erbse::Parser.new.call("<% [].each do %>\n<% next if true %>\n<% end %>")
 => [:multi, [:newline], [:block, " next if true ", [:multi, [:newline]]]]

If statement incorrectly parses "end" as a keyword

Hi,

Consider this ERB content:

<% if 'This is a string with the end keyword in it' %>
Content
<% end %>

I would expect this to parse fine. However, it seems that the "end" within the string is detected as an actual end keyword.

Erbse::Engine.new.call("<% if 'This is a string with the end keyword in it' %> Content  <% end %>")
NoMethodError: undefined method `<<' for nil:NilClass
from /usr/local/bundle/gems/erbse-0.1.4/lib/erbse/parser.rb:38:in `block in call'

It's not just within strings, but anything with "end" in it, for example and object of a class that defines an end method:

<% if some_object.end %>
Content
<% end %>

The issue is that buffers is an empty array on this line:

buffers.last << [:static, "#{text}\n"] << [:newline]

doesn't work with case statements

Yes I know that logic in views is a code smell, but I have to work with legacy code. However...

While upgrading cells from 3.x to 4.1.7 I've come across a problem. A template with a massive case statement does not work. If I cut it back to the simplest possible case statement I still get this

   NoMethodError:
   undefined method `<<' for nil:NilClass
  # Irrelevant_stuff/gems/erbse-0.1.3/lib/erbse/parser.rb:62:in `block in call'

I've had to change the template to lots of if .... elsif.... and that does work.

missing whitespaces between dynamic nodes

<div class="class1 <%= 'class2' %> <%= 'class3' %>></div>

evaluates to

<div class="class1 class2class3"></div>
2.3.3 :001 > require 'erbse'
 => true
2.3.3 :002 > eval Erbse::Engine.new.call(%{<div class="class1 <%= 'class2' %> <%= 'class3' %>"></div>})
 => "<div class=\"class1 class2class3\"></div>"
2.3.3 :003 >

is this intended?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.