Search code examples
groovytemplate-engine

Groovy TemplateEngine - function for markup creation


I'm a JS programmer trying to write some Groovy code (with no Java background at all). I need to write some templates using Groovy, so I created a function in order to avoid repetition. My goal is to be able to pass html objects to the function (for example: p(), div(), span() and so on), but is isn't working as I expected:

The function

void addon ( addonType, mainHolder, content ) {
  div( class: "addon " + addonType ) {
    div( class: "addon-main" ) {
      div( class: "addon-main-holder" ) {
        yieldUnescaped mainHolder
      }
    }

    div( class: "addon-content" ) {
        yieldUnescaped content
    }
  }
}

Doesn't works:

[...]
  body {
    addon( 'addon-warning', p('Lorem Ipsum'), p('Dolor sit amet consectetur') )
  }
[...]

Works:

[...]
  body {
    addon( 'addon-warning', '<p>Lorem Ipsum</p>', '<p>Dolor sit amet consectetur</p>') )
  }
[...]

I tried some variations, using yield rather than yieldUnescaped, but no success. Is it possible? Any help would be much appreciated.


Solution

  • Assuming you want to pass in further DSL-based tags into your addon function, I'd pass closure to that function instead. This is an simplified, self containing version (which makes it bit harder to read, as the template is in a string; take a look at the XXX comments):

    import groovy.text.markup.*
    
    def config = new TemplateConfiguration()
    def engine = new MarkupTemplateEngine(config)
    def template = engine.createTemplate('''
    html {
        body {
            addon("Hello World", { // XXX: pass a closure
                p("Lorem Ipsum")
                p("Lorem Ipsum")
                p("Lorem Ipsum")
            })
        }
    }
    
    void addon(title, content) {
        h1(title)
        div {
            content() // XXX call the closure
        }
    }
    ''')
    Writable output = template.make([:])
    println output
    // => <html><body><h1>Hello World</h1><div><p>Lorem Ipsum</p><p>Lorem Ipsum</p><p>Lorem Ipsum</p></div></body></html>