/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. */
  18. package org.fusesource.scalate.mustache
  19. import org.fusesource.scalate._
  20. import support.{ Code, AbstractCodeGenerator }
  21. import collection.mutable.Stack
  22. import util.Log
  23. import scala.language.implicitConversions
  24. object MustacheCodeGenerator extends Log
  25. /**
  26. * @version $Revision: 1.1 $
  27. */
  28. class MustacheCodeGenerator extends AbstractCodeGenerator[Statement] {
  29. import MustacheCodeGenerator._
  30. override val stratumName = "MSC"
  31. implicit def textToString(text: Text) = text.value
  32. implicit def textOptionToString(text: Option[Text]): Option[String] = text match {
  33. case None => None
  34. case Some(x) => Some(x.value)
  35. }
  36. private class SourceBuilder extends AbstractSourceBuilder[Statement] {
  37. protected val scopes = new Stack[String]
  38. protected var scopeIndex = 1
  39. protected def isImportStatementOrCommentOrWhitespace(fragment: Statement) = fragment match {
  40. //case s: Text if (s.value.trim.length == 0) => true
  41. case s: Comment => true
  42. case _ => false
  43. }
  44. def generate(fragments: List[Statement]): Unit = {
  45. this << "import _root_.org.fusesource.scalate.mustache._"
  46. this << ""
  47. this << "val " + pushScope + " = " + "Scope($_scalate_$_context)"
  48. fragments.foreach(generate)
  49. }
  50. def generate(fragment: Statement): Unit = {
  51. fragment match {
  52. case Comment(code) => {
  53. }
  54. case Text(text) => {
  55. this << fragment.pos
  56. this << "$_scalate_$_context << ( " + asString(text) + " )"
  57. }
  58. case Variable(name, unescape) => {
  59. this << fragment.pos
  60. this << "" + scope + ".renderVariable(\"" + name + "\", " + unescape + ")"
  61. }
  62. case Section(name, body) => {
  63. this << fragment.pos
  64. this << "" + scope + ".section(\"" + name + "\") { " + pushScope + " =>"
  65. indent {
  66. body.foreach(generate)
  67. }
  68. popScope
  69. this << "}"
  70. }
  71. case InvertSection(name, body) => {
  72. this << fragment.pos
  73. this << "" + scope + ".invertedSection(\"" + name + "\") { " + pushScope + " =>"
  74. indent {
  75. body.foreach(generate)
  76. }
  77. popScope
  78. this << "}"
  79. }
  80. case Partial(name) => {
  81. this << fragment.pos
  82. this << "" + scope + ".partial(\"" + name + "\")"
  83. }
  84. case ImplicitIterator(name) => {
  85. this << fragment.pos
  86. this << "" + scope + ".implicitIterator = Some(\"" + name + "\")"
  87. }
  88. case Pragma(name, options) =>
  89. this << fragment.pos
  90. this << "$_scalate_$_context << \"ERROR: This implementation of mustache doesn't understand the '" + name + "' pragma\""
  91. case SetDelimiter(open, close) =>
  92. case s => {
  93. warn("Unsupported statement: %s", s)
  94. }
  95. }
  96. }
  97. def scope = scopes.head
  98. protected def pushScope: String = {
  99. val name = "$_scope_" + scopeIndex
  100. scopeIndex += 1
  101. scopes.push(name)
  102. name
  103. }
  104. protected def popScope = scopes.pop
  105. }
  106. override def generate(engine: TemplateEngine, source: TemplateSource, bindings: Iterable[Binding]): Code = {
  107. // Load the translation unit
  108. val content = source.text
  109. val uri = source.uri
  110. // Parse the translation unit
  111. val fragments = (new MustacheParser).parse(content)
  112. val sb = new SourceBuilder
  113. sb.generate(engine, source, bindings, fragments)
  114. Code(source.className, sb.code, Set(uri), sb.positions)
  115. }
  116. }