PageRenderTime 27ms CodeModel.GetById 13ms app.highlight 10ms RepoModel.GetById 2ms app.codeStats 0ms

/scalate-core/src/main/scala/org/fusesource/scalate/mustache/MustacheCodeGenerator.scala

http://github.com/scalate/scalate
Scala | 137 lines | 93 code | 21 blank | 23 comment | 0 complexity | e2ac4de41f31769fe1788fc55b64eba4 MD5 | raw file
  1/**
  2 * Copyright (C) 2009-2011 the original author or authors.
  3 * See the notice.md file distributed with this work for additional
  4 * information regarding copyright ownership.
  5 *
  6 * Licensed under the Apache License, Version 2.0 (the "License");
  7 * you may not use this file except in compliance with the License.
  8 * You may obtain a copy of the License at
  9 *
 10 *     http://www.apache.org/licenses/LICENSE-2.0
 11 *
 12 * Unless required by applicable law or agreed to in writing, software
 13 * distributed under the License is distributed on an "AS IS" BASIS,
 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 15 * See the License for the specific language governing permissions and
 16 * limitations under the License.
 17 */
 18package org.fusesource.scalate.mustache
 19
 20import org.fusesource.scalate._
 21import support.{ Code, AbstractCodeGenerator }
 22import collection.mutable.Stack
 23import util.Log
 24
 25import scala.language.implicitConversions
 26
 27object MustacheCodeGenerator extends Log
 28
 29/**
 30 * @version $Revision: 1.1 $
 31 */
 32class MustacheCodeGenerator extends AbstractCodeGenerator[Statement] {
 33  import MustacheCodeGenerator._
 34
 35  override val stratumName = "MSC"
 36
 37  implicit def textToString(text: Text) = text.value
 38
 39  implicit def textOptionToString(text: Option[Text]): Option[String] = text match {
 40    case None => None
 41    case Some(x) => Some(x.value)
 42  }
 43
 44  private class SourceBuilder extends AbstractSourceBuilder[Statement] {
 45    protected val scopes = new Stack[String]
 46    protected var scopeIndex = 1
 47
 48    protected def isImportStatementOrCommentOrWhitespace(fragment: Statement) = fragment match {
 49      //case s: Text if (s.value.trim.length == 0) => true
 50      case s: Comment => true
 51      case _ => false
 52    }
 53
 54    def generate(fragments: List[Statement]): Unit = {
 55      this << "import _root_.org.fusesource.scalate.mustache._"
 56      this << ""
 57
 58      this << "val " + pushScope + " = " + "Scope($_scalate_$_context)"
 59
 60      fragments.foreach(generate)
 61    }
 62
 63    def generate(fragment: Statement): Unit = {
 64      fragment match {
 65        case Comment(code) => {
 66        }
 67        case Text(text) => {
 68          this << fragment.pos
 69          this << "$_scalate_$_context << ( " + asString(text) + " )"
 70        }
 71        case Variable(name, unescape) => {
 72          this << fragment.pos
 73          this << "" + scope + ".renderVariable(\"" + name + "\", " + unescape + ")"
 74        }
 75        case Section(name, body) => {
 76          this << fragment.pos
 77          this << "" + scope + ".section(\"" + name + "\") { " + pushScope + " =>"
 78          indent {
 79            body.foreach(generate)
 80          }
 81          popScope
 82          this << "}"
 83        }
 84        case InvertSection(name, body) => {
 85          this << fragment.pos
 86          this << "" + scope + ".invertedSection(\"" + name + "\") { " + pushScope + " =>"
 87          indent {
 88            body.foreach(generate)
 89          }
 90          popScope
 91          this << "}"
 92        }
 93        case Partial(name) => {
 94          this << fragment.pos
 95          this << "" + scope + ".partial(\"" + name + "\")"
 96        }
 97        case ImplicitIterator(name) => {
 98          this << fragment.pos
 99          this << "" + scope + ".implicitIterator = Some(\"" + name + "\")"
100        }
101        case Pragma(name, options) =>
102          this << fragment.pos
103          this << "$_scalate_$_context << \"ERROR: This implementation of mustache doesn't understand the '" + name + "' pragma\""
104        case SetDelimiter(open, close) =>
105        case s => {
106          warn("Unsupported statement: %s", s)
107        }
108      }
109    }
110
111    def scope = scopes.head
112
113    protected def pushScope: String = {
114      val name = "$_scope_" + scopeIndex
115      scopeIndex += 1
116      scopes.push(name)
117      name
118    }
119
120    protected def popScope = scopes.pop
121  }
122
123  override def generate(engine: TemplateEngine, source: TemplateSource, bindings: Iterable[Binding]): Code = {
124
125    // Load the translation unit
126    val content = source.text
127    val uri = source.uri
128
129    // Parse the translation unit
130    val fragments = (new MustacheParser).parse(content)
131
132    val sb = new SourceBuilder
133    sb.generate(engine, source, bindings, fragments)
134
135    Code(source.className, sb.code, Set(uri), sb.positions)
136  }
137}