Open ghost opened 9 years ago
Ahh, yes, I ran into this as well. At a minimum, this should perhaps be mentioned in the docs.
I messed around with this today:
scala> import scalatags.PrettyText.all._
import scalatags.PrettyText.all._
scala> val frag = html(
| head(
| script("some script")
| ),
| body(
| h1("This is my title"),
| div(
| p("This is my first paragraph"),
| p("This is my second paragraph")
| )
| )
| )
frag: scalatags.PrettyText.TypedTag[String] =
<html>
<head>
<script>
some script
</script>
</head>
<body>
<h1>
This is my title
</h1>
<div>
<p>
This is my first paragraph
</p>
<p>
This is my second paragraph
</p>
</div>
</body>
</html>
Basically PrettyText is a cloned Text backend with prettier output. It's just a newline per tag and two spaces indent. I had to add a depth parameter to Frag.writeTo (strb, depth)
but otherwise core scalatags is unchanged. I could perhaps make the additional parameter exclusive to PrettyText
with some more effort.
What do you think? You've had a few spurious issues caused by pretty printing using scala.xml.
For my use case this is perfect.
I just need to see how the HTML is visually rendered (when using complex functions that generate HTML). The above indentation method allows me to do this quickly. I will only use this when in development and switch to the standard Text backend for production.
Regarding the technical aspects of the implementation, if PrettyText is a lot of cloned code this might make maintenance of the code more effort going forward. As both PrettyText and Text might potentially need to be changed. Not sure if PrettyText functionality could be added as a method of Text to reduce any potential code duplication ( caveat... I've not looked at the code in detail )
Thanks again.
I'll make a fork and push the branch when my power comes back on... It's certainly not slick but for 100 loc or so , mostly copied, it's a decent result.
200 loc or so actually, and I was hoping @lihaoyi would weigh in before I put more effort into this...
Sorry, will take a look On Apr 9, 2015 05:13, "mark lister" notifications@github.com wrote:
200 loc or so actually, and I was hoping @lihaoyi https://github.com/lihaoyi would weigh in before I put more effort into this...
— Reply to this email directly or view it on GitHub https://github.com/lihaoyi/scalatags/issues/76#issuecomment-91211959.
My power just came back on but I'd been out drinking in the interrum so my skills are a little impaired :)
Anyway just forked and pushed branch prettytext. Not a pull request as it's pretty rough, just for discussion really.
I had much better idea which I'll implement soon. Sorry about the noise.
branch prettytext2
It provides an implict class on a Text.TypedTag which has basic structured output. Totally non-invasive to scalatags and controlled by an import. First try and again, for discussion.
Welcome to Scala version 2.11.4 (OpenJDK Server VM, Java 1.7.0_75).
Type in expressions to have them evaluated.
Type :help for more information.
scala> import scalatags.Text.all._
import scalatags.Text.all._
scala> import scalatags.text.Pretty._
import scalatags.text.Pretty._
scala> div(
| div(id:="ch1Panel", role:="tabpanel", aria.labelledby:="ch1Tab")(
| "Chapter 1 content goes here"
| ),
| div(id:="ch2Panel", role:="tabpanel", aria.labelledby:="ch2Tab")(
| "Chapter 2 content goes here"
| ),
| div(id:="quizPanel", role:="tabpanel", aria.labelledby:="quizTab")(
| "Quiz content goes here"
| )
| )
res1: scalatags.Text.TypedTag[String] = <div><div id="ch1Panel" role="tabpanel" aria-labelledby="ch1Tab">Chapter 1 content goes here</div><div id="ch2Panel" role="tabpanel" aria-labelledby="ch2Tab">Chapter 2 content goes here</div><div id="quizPanel" role="tabpanel" aria-labelledby="quizTab">Quiz content goes here</div></div>
scala> res1.pretty
res2: scalatags.text.Pretty.PrettyFrag =
<div>
<div id="ch1Panel" role="tabpanel" aria-labelledby="ch1Tab">
Chapter 1 content goes here
</div>
<div id="ch2Panel" role="tabpanel" aria-labelledby="ch2Tab">
Chapter 2 content goes here
</div>
<div id="quizPanel" role="tabpanel" aria-labelledby="quizTab">
Quiz content goes here
</div>
</div>
Want to send a PR? This sounds pretty self-contained and uncontroversial
@lihaoyi you can take a look, it's PR #80....
Native pretty print is a good choice.
Meanwhile if you need html pretty print, try HtmlCleaner: http://htmlcleaner.sourceforge.net/
One might say that it is overkill, but it works.
Example:
val h = html(
head(
script("some script"),
script(src:="/assets/jquery.min.js")
),
body(
h1("This is my title"),
div(
h1(backgroundColor:="blue", color:="red")("This is my title"),
div(backgroundColor:="blue", color:="red")(
p(cls := "contentpara first")(
"This is my first paragraph"
),
a(opacity:=0.9)(
p(cls := "contentpara")("Goooogle")
)
),
"A B C",
p("Hello World!!!"),
p("I am ScalaTags!!!"),
p("onclick".attr:="... do some js")(
"This is my first paragraph"
),
a("href".attr:="http://www.google.com")(
p("Goooogle")
)
)
)
)
logger.debug("html = \n" + "<!DOCTYPE html>" + h.render)
import org.htmlcleaner
// create an instance of HtmlCleaner
val cleaner = new org.htmlcleaner.HtmlCleaner();
// take default cleaner properties
val props = cleaner.getProperties();
val tag = cleaner.clean("<!DOCTYPE html>" + h.render)
val pretty = new PrettyHtmlSerializer(props, " ")
logger.debug("html = \n" + pretty.getAsString(tag))
This will produce:
13:42:24.243 [run-main-1] DEBUG Main$ - html =
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html>
<head>
<script>some script</script>
<script src="/assets/jquery.min.js"></script>
</head>
<body>
<h1>This is my title</h1>
<div>
<h1 style="background-color: blue;color: red;">This is my title</h1>
<div style="background-color: blue;color: red;">
<p class="contentpara first">This is my first paragraph</p>
<a style="opacity: 0.9;">
<p class="contentpara">Goooogle</p>
</a>
</div>A B C
<p>Hello World!!!</p>
<p>I am ScalaTags!!!</p>
<p onclick="... do some js">This is my first paragraph</p>
<a href="http://www.google.com">
<p>Goooogle</p>
</a>
</div>
</body>
</html>
@lihaoyi, please merge
Side note: pretty-printed HTML may yield different rendering in browser. Example:
<!-- renders helloworld-->
<div><div style="display:inline-block">hello</div><div style="display:inline-block">world</div></div>
<!-- renders hello world-->
<div>
<div style="display:inline-block">hello</div>
<div style="display:inline-block">world</div>
</div>
scala.xml.PrettyPrinter does not generate validate W3 html markup language, and alters the orginal placements of tags.
For example script(src:=""/assets/jquery.min.js"") generates < script src="/assets/jquery.min.js"></script> and is converted to < script src="/assets/jquery.min.js"/>
When in development it is useful to see the structure of the HTML, however by using scala.xml.PrettyPrinter as described in the readme.md the output is changed and becomes invalid.
Would it be possible to create a basic pretty-print within scalatags itself, I don't think you would need to wrap long lines of text, but showing the correct indentation would be enough.