Index: src/test/java/org/apache/sling/microsling/integration/NodetypeRenderingTest.java =================================================================== --- src/test/java/org/apache/sling/microsling/integration/NodetypeRenderingTest.java (revision 591525) +++ src/test/java/org/apache/sling/microsling/integration/NodetypeRenderingTest.java (working copy) @@ -119,4 +119,15 @@ testClient.delete(toDelete); } } -} \ No newline at end of file + + public void testErbHtml() throws IOException { + final String toDelete = uploadTestScript("rendering-test.erb","html.erb"); + try { + final String content = getContent(displayUrl + ".html", CONTENT_TYPE_HTML); + assertTrue("Content includes Ruby marker",content.contains("Ruby template")); + assertTrue("Content contains formatted test text",content.contains("

" + testText + "

")); + } finally { + testClient.delete(toDelete); + } + } +} Index: src/test/resources/integration-test/rendering-test.erb =================================================================== --- src/test/resources/integration-test/rendering-test.erb (revision 0) +++ src/test/resources/integration-test/rendering-test.erb (revision 0) @@ -0,0 +1,15 @@ +!-- used by ScriptedRenderingTest --> + + +

Ruby template <%= Time.now %>

+

<%= resource.getRawData().getProperty("text").getString() %>

+ <% unless props.nil? or props.empty? %> + + <% for prop, val in props %> + + <% end %> +
<%= prop %>:<%= val %>
+ <% end %> + + + Index: src/main/java/org/apache/sling/microsling/scripting/engines/ruby/ErbScriptEngine.java =================================================================== --- src/main/java/org/apache/sling/microsling/scripting/engines/ruby/ErbScriptEngine.java (revision 0) +++ src/main/java/org/apache/sling/microsling/scripting/engines/ruby/ErbScriptEngine.java (revision 0) @@ -0,0 +1,108 @@ +package org.apache.sling.microsling.scripting.engines.ruby; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintStream; +import java.io.Reader; +import java.io.Writer; +import java.util.Map; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.apache.sling.api.HttpStatusCodeException; +import org.apache.sling.api.SlingException; +import org.apache.sling.api.scripting.SlingScript; +import org.apache.sling.api.scripting.SlingScriptEngine; +import org.jruby.Ruby; +import org.jruby.RubyModule; +import org.jruby.RubySymbol; +import org.jruby.javasupport.JavaEmbedUtils; +import org.jruby.runtime.builtin.IRubyObject; + +/** + * A ScriptEngine that uses ruby erb templates to render a Resource + */ +public class ErbScriptEngine implements SlingScriptEngine { + + public static final String RUBY_SCRIPT_EXTENSION = "erb"; + public Ruby runtime; + RubySymbol bindingSym; + RubyModule erbModule; + + public ErbScriptEngine() throws SlingException { + runtime = Ruby.getDefaultInstance(); + + runtime.evalScript("require 'java';require 'erb';self.send :include, ERB::Util;class ERB;def get_binding;binding;end;attr_reader :props;def set_props(p);@props = p;" + + "for name,v in @props;instance_eval \"def #{name}; @props['#{name}'];end\";end;end;end;"); + + erbModule = runtime.getClassFromPath("ERB"); + bindingSym = RubySymbol.newSymbol(runtime, "get_binding"); + } + + public String[] getExtensions() { + return new String[]{RUBY_SCRIPT_EXTENSION}; + } + + public String getEngineName() { + return "Ruby Erb Script Engine"; + } + + public String getEngineVersion() { + return "0.9"; + } + + public void eval(SlingScript script, Map props) + throws SlingException, IOException { + // ensure get method + HttpServletRequest request = (HttpServletRequest) props.get(REQUEST); + if(!"GET".equals(request.getMethod())) { + throw new HttpStatusCodeException( + HttpServletResponse.SC_METHOD_NOT_ALLOWED, + "Ruby templates only support GET requests"); + } + + try { + final Writer w = ((HttpServletResponse) props.get(RESPONSE)).getWriter(); + PrintStream stream = new PrintStream(new OutputStream() { + public void write(int b) { + try { + w.write(b); + } catch(IOException ex) { + } + } + }); + + StringBuffer scriptString = new StringBuffer(); + BufferedReader bufferedScript = (BufferedReader) script.getScriptReader(); + String nextLine = bufferedScript.readLine(); + while(nextLine != null) { + scriptString.append(nextLine); + scriptString.append("\n"); + nextLine = bufferedScript.readLine(); + } + + IRubyObject scriptRubyString = JavaEmbedUtils.javaToRuby(runtime, scriptString.toString()); + IRubyObject erb = (IRubyObject) JavaEmbedUtils + .invokeMethod(runtime, erbModule, "new", new Object[]{scriptRubyString}, IRubyObject.class); + + JavaEmbedUtils.invokeMethod(runtime, erb, "set_props", + new Object[]{JavaEmbedUtils.javaToRuby(runtime, props)}, IRubyObject.class); + + IRubyObject binding = (IRubyObject) JavaEmbedUtils + .invokeMethod(runtime, erb, "send", new Object[]{bindingSym}, IRubyObject.class); + + String out = (String) JavaEmbedUtils.invokeMethod(runtime, erb, "result", + new Object[]{(Object) binding}, String.class); + + stream.println(out); + stream.flush(); + + } catch(IOException ioe) { + throw ioe; + } catch(Throwable t) { + throw new SlingException("Failure running Ruby script ", t); + } + } +} Index: src/main/java/org/apache/sling/microsling/scripting/MicroslingScriptResolver.java =================================================================== --- src/main/java/org/apache/sling/microsling/scripting/MicroslingScriptResolver.java (revision 591525) +++ src/main/java/org/apache/sling/microsling/scripting/MicroslingScriptResolver.java (working copy) @@ -42,6 +42,7 @@ import org.apache.sling.api.scripting.SlingScriptResolver; import org.apache.sling.microsling.resource.JcrNodeResource; import org.apache.sling.microsling.scripting.engines.freemarker.FreemarkerScriptEngine; +import org.apache.sling.microsling.scripting.engines.ruby.ErbScriptEngine; import org.apache.sling.microsling.scripting.engines.rhino.RhinoJavasSriptEngine; import org.apache.sling.microsling.scripting.engines.velocity.VelocityTemplatesScriptEngine; import org.apache.sling.microsling.scripting.helpers.ScriptFilenameBuilder; @@ -80,6 +81,7 @@ addScriptEngine(new RhinoJavasSriptEngine()); addScriptEngine(new VelocityTemplatesScriptEngine()); addScriptEngine(new FreemarkerScriptEngine()); + addScriptEngine(new ErbScriptEngine()); } /** Index: src/main/webapp/erb-scripts.html =================================================================== --- src/main/webapp/erb-scripts.html (revision 0) +++ src/main/webapp/erb-scripts.html (revision 0) @@ -0,0 +1,39 @@ + + + microsling Ruby Erb templates + + + +

microsling Ruby Erb templates

+ +
+ back to homepage +
+

+ Scripts found by the SlingScriptResolver using the .erb extension are executed by + the ErbScriptEngine. +

+

+ This works exactly like the Velocity templates, except that + templates use the Erb syntax. +

+

+ Here's an example HTML template. See the Erb docs website + more info about the syntax. +

+      <html>
+        <body>
+          <p><span>This is an example Erb template <%= Time.now %></span></p>
+          <p><span><%= resource.getItem().getProperty("text").getString() %></span></p>
+          <% unless props.nil? or props.empty? %>
+            <table>
+              <% for prop, val in props %>
+                <tr><td><b><%= prop %></b>:</td><td><%= val %></td></tr>
+              <% end %>
+            </table>
+          <% end %>
+        </body>
+      </html>
+

+ + Index: src/main/webapp/index.html =================================================================== --- src/main/webapp/index.html (revision 591525) +++ src/main/webapp/index.html (working copy) @@ -40,6 +40,11 @@ FreeMarker templates : explains how to use FreeMarker templates to render content. +
  • + + Ruby Erb templates + : explains how to use Ruby Erb templates to render content. +
  • Show me the code

    @@ -144,4 +149,4 @@

    - \ No newline at end of file + Index: pom.xml =================================================================== --- pom.xml (revision 591525) +++ pom.xml (working copy) @@ -56,6 +56,11 @@ + org.jruby + jruby-complete + 1.0RC3 + + org.apache.sling sling-api 2.0.0-incubator-SNAPSHOT