PageRenderTime 27ms CodeModel.GetById 16ms app.highlight 8ms RepoModel.GetById 1ms app.codeStats 0ms

/scalate-core/src/main/scala/org/fusesource/scalate/support/RenderHelper.scala

http://github.com/scalate/scalate
Scala | 148 lines | 96 code | 8 blank | 44 comment | 1 complexity | 3229d3b65a6fd65902006c493eda84b9 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/*
 19  * Copyright (c) 2009 Matthew Hildebrand <matt.hildebrand@gmail.com>
 20 *
 21 * Permission to use, copy, modify, and/or distribute this software for any
 22 * purpose with or without fee is hereby granted, provided that the above
 23 * copyright notice and this permission notice appear in all copies.
 24 *
 25 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 26 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 27 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 28 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 29 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 30 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 31 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 32 */
 33
 34package org.fusesource.scalate
 35package support
 36
 37import scala.collection.mutable.LinkedHashMap
 38
 39object RenderHelper {
 40
 41  /**
 42   * Pads the text following newlines with the specified
 43   * indent amount so that the text is indented.
 44   */
 45  def indent(amount: String, text: Any): String = text.toString.replaceAll("\n(.)", "\n" + amount + "$1")
 46
 47  def indentAmount(level: Int, kind: String): String = {
 48    val rc = new StringBuilder
 49    var i = 0
 50    while (i < level) {
 51      rc.append(kind)
 52      i += 1
 53    }
 54    rc.toString
 55  }
 56
 57  /**
 58   * Converts newlines into the XML entity: &#x000A;
 59   * so that multiple lines encode to a sinle long HTML source line
 60   * but still render in browser as multiple lines.
 61   */
 62  def preserve(text: Any): String = text.toString.replaceAll("\n", "&#x000A;")
 63
 64  /**
 65   *  Escapes any XML special characters.
 66   */
 67  def sanitize(text: String): String =
 68    text.foldLeft(new StringBuffer)((acc, ch) => sanitize(ch, acc)).toString
 69
 70  private def sanitize(ch: Char, buffer: StringBuffer): StringBuffer = {
 71    ch match {
 72      case '"' => buffer.append("&quot;")
 73      case '&' => buffer.append("&amp;")
 74      case '<' => buffer.append("&lt;")
 75      case '>' => buffer.append("&gt;")
 76      // Not sure if there are other chars the need sanitization.. but if we do find
 77      // some, then the following might work:
 78      //    case xxx   => buffer.append( "&#x" + ch.toInt.toHexString + ";" )
 79      case _ => buffer.append(ch)
 80    }
 81  }
 82
 83  def attributes(context: RenderContext, entries: List[(Any, Any)]): Unit = {
 84
 85    val (entries_class, tmp) = entries.partition { x => { x._1 match { case "class" => true; case _ => false } } }
 86    val (entries_id, entries_rest) = tmp.partition { x => { x._1 match { case "id" => true; case _ => false } } }
 87    val map = LinkedHashMap[Any, Any]()
 88
 89    def isEnabled(value: Any) = value != null && (!value.isInstanceOf[Boolean] || value.asInstanceOf[Boolean])
 90
 91    val flattener = (x: (Any, Any)) => {
 92      if (isEnabled(x._2)) {
 93        List(x._2)
 94      } else {
 95        Nil
 96      }
 97    }
 98
 99    val ids = entries_id.flatMap(flattener)
100    if (!ids.isEmpty) {
101      map += "id" -> ids.last
102    }
103
104    val classes = entries_class.flatMap(flattener)
105    if (!classes.isEmpty) {
106      map += "class" -> classes.mkString(" ")
107    }
108
109    entries_rest.foreach { me => map += me._1 -> me._2 }
110
111    if (!map.isEmpty) {
112      map.foreach {
113        case (name, value) =>
114          if (isEnabled(value)) {
115            context << " "
116            context << name
117            context << "=\""
118            if (value.isInstanceOf[Boolean]) {
119              context << name
120            } else {
121              context.escape(value)
122            }
123            context << "\""
124          }
125      }
126    }
127
128  }
129
130  def smart_sanitize(context: RenderContext, value: Any): String = {
131    context.value(value).toString
132    /*
133    if (value == null) {
134      return context.value(value);
135    }
136    value match {
137      case x: Node =>
138        context.value(value)
139
140      case x: Traversable[Any] =>
141        x.map( smart_sanitize(context, _) ).mkString("")
142
143      case _ =>
144        sanitize(context.value(value, false))
145    }
146*/
147  }
148}