diff --git a/scalatags/shared/src/main/scala/scalatags/Text.scala b/scalatags/shared/src/main/scala/scalatags/Text.scala index cdba63b0..b6dade22 100644 --- a/scalatags/shared/src/main/scala/scalatags/Text.scala +++ b/scalatags/shared/src/main/scala/scalatags/Text.scala @@ -98,17 +98,23 @@ object Text Objects.requireNonNull(v) def render = { val strb = new StringBuilder() - writeTo(strb) + writeTo(strb, 0, 0, false) strb.toString() } - def writeTo(strb: StringBuilder) = Escaping.escape(v, strb) + def writeTo(strb: StringBuilder, indentBy: Int, depth: Int, fromTag: Boolean) = { + Escaping.escape(v, strb) + false + } } object StringFrag extends Companion[StringFrag] object RawFrag extends Companion[RawFrag] case class RawFrag(v: String) extends text.Frag { Objects.requireNonNull(v) def render = v - def writeTo(strb: StringBuilder) = strb ++= v + def writeTo(strb: StringBuilder, indentBy: Int, depth: Int, fromTag: Boolean) = { + strb ++= v + false + } } class GenericAttr[T] extends AttrValue[T]{ @@ -157,38 +163,63 @@ object Text * because I've inlined a whole lot of things to improve the performance of this code * ~4x from what it originally was, which is a pretty nice speedup */ - def writeTo(strb: StringBuilder): Unit = { + override def writeTo(strb: StringBuilder, indentBy: Int, depth: Int, fromTag: Boolean) = { val builder = new text.Builder() build(builder) + val indenting = indentBy > 0 + val indent: String = if(indenting) " " * (indentBy * depth) else null + // tag + if(indenting && fromTag) { + strb += '\n' + strb ++= indent + } strb += '<' ++= tag // attributes - var i = 0 - while (i < builder.attrIndex){ - val pair = builder.attrs(i) - strb += ' ' ++= pair._1 ++= "=\"" - Escaping.escape(pair._2, strb) - strb += '\"' - i += 1 + { + var i = 0 + while (i < builder.attrIndex){ + val pair = builder.attrs(i) + strb += ' ' ++= pair._1 ++= "=\"" + Escaping.escape(pair._2, strb) + strb += '\"' + i += 1 + } } - if (builder.childIndex == 0 && void) { - // No children - close tag - strb ++= " />" + if (builder.childIndex == 0) { + if (void) { + // No children - self-closing tag + strb ++= " />" + } else { + // no children - close tag + strb ++= ">" ++= tag += '>' + } } else { strb += '>' + var ft = true + // Childrens - var i = 0 - while(i < builder.childIndex){ - builder.children(i).writeTo(strb) - i += 1 + { + val d = depth + 1 + var i = 0 + while (i < builder.childIndex) { + ft = builder.children(i).writeTo(strb, indentBy, d, ft) + i += 1 + } } // Closing tag + if(indenting && ft) { + strb += '\n' + strb ++= indent + } strb ++= "" ++= tag += '>' } + + true } def apply(xs: Modifier*): TypedTag[Output] = { @@ -198,12 +229,20 @@ object Text /** * Converts an ScalaTag fragment into an html string */ - override def toString = { + final def toString(indentBy: Int) = { val strb = new StringBuilder - writeTo(strb) + writeTo(strb, indentBy, 0, false) strb.toString() } - def render: Output = this.toString.asInstanceOf[Output] + + /** + * Converts an ScalaTag fragment into an html string + */ + override final def toString = toString(0) + + def render(indentBy: Int): Output = this.toString(indentBy).asInstanceOf[Output] + + def render: Output = render(0) } diff --git a/scalatags/shared/src/main/scala/scalatags/text/Builder.scala b/scalatags/shared/src/main/scala/scalatags/text/Builder.scala index cc865649..a0b7f414 100644 --- a/scalatags/shared/src/main/scala/scalatags/text/Builder.scala +++ b/scalatags/shared/src/main/scala/scalatags/text/Builder.scala @@ -67,7 +67,15 @@ class Builder(var children: Array[Frag] = new Array(4), } } trait Frag extends generic.Frag[Builder, String]{ - def writeTo(strb: StringBuilder): Unit - def render: String - def applyTo(b: Builder) = b.addChild(this) + /** + * Write into a string buffer. + * + * @param strb buffer to write into + * @param indentBy the amount to indent per unit depth + * @param depth depth of this node + * @param fromTag true if the previous node to be written to strb is a tag + * @return true if the last thing to be written to strb by this method was a tag + */ + def writeTo(strb: StringBuilder, indentBy: Int, depth: Int, fromTag: Boolean): Boolean + override def applyTo(b: Builder) = b.addChild(this) } diff --git a/scalatags/shared/src/test/scala/scalatags/text/TextTests.scala b/scalatags/shared/src/test/scala/scalatags/text/TextTests.scala index 4bab9305..1c20f3f0 100644 --- a/scalatags/shared/src/test/scala/scalatags/text/TextTests.scala +++ b/scalatags/shared/src/test/scala/scalatags/text/TextTests.scala @@ -10,6 +10,77 @@ object TextTests extends TestSuite{ val sample = div("omg") assert(sample.toString == "