All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.fusesource.scalate.tool.commands.ToScaml.scala Maven / Gradle / Ivy

/**
 * Copyright (C) 2009-2011 the original author or authors.
 * See the notice.md file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.fusesource.scalate.tool.commands

import org.apache.felix.gogo.commands.{ Action, Option => option, Argument => argument, Command => command }
import scala.xml._
import java.io._
import java.net.URL
import org.fusesource.scalate.util.IOUtil
import org.fusesource.scalate.ssp._
import org.w3c.tidy.Tidy
import org.apache.felix.service.command.CommandSession

/**
 * 

*

* * @author Hiram Chirino */ @command(scope = "scalate", name = "toscaml", description = "Converts an XML or HTML file to Scaml") class ToScaml extends Action { @option(name = "--tidy", description = "Should html be tidied first?") var tidy = true @argument(index = 0, name = "from", description = "The input file or http URL. If ommited, input is read from the console") var from: String = _ @argument(index = 1, name = "to", description = "The output file. If ommited, output is written to the console") var to: File = _ var out: IndentPrintStream = _ def execute(session: CommandSession): AnyRef = { def doit(): Unit = { val in = if (from == null) { session.getKeyboard } else { if (from.startsWith("http://") || from.startsWith("https://")) { new URL(from).openStream } else { new FileInputStream(from) } } var data = IOUtil.loadBytes(in) //println("original: "+new String(data, "UTF-8")) // Parse out the code bits and wrap them in script tags so that // we can tidy the document. val fragments = (new SspParser).getPageFragments(new String(data, "UTF-8")) data = ("
" + (fragments.map(_ match { case ExpressionFragment(code) => "#{" + code.value + "}" case ScriptletFragment(code) => """""" case CommentFragment(comment) => """""" case TextFragment(text) => text.value case unexpected: PageFragment => System.err.println("Unexpected page fragment " + unexpected) "" // skip it }).mkString("")) + "
").getBytes("UTF-8") // println("escaped: "+new String(data, "UTF-8")) // try to tidy the html first before we try to parse it as XML if (tidy) { val tidy = new Tidy tidy.setXHTML(true) tidy.setXmlTags(true) tidy.setIndentCdata(false) tidy.setEscapeCdata(false) tidy.setQuiet(true) val out = new ByteArrayOutputStream() tidy.parse(new ByteArrayInputStream(data), out); data = out.toByteArray // println("tidy: "+new String(data, "UTF-8")) } // Try to strip out the doc type... stuff.. { val text = new String(data, "UTF-8").trim if (text.startsWith("') + 1).getBytes("UTF-8") // println("doctype: "+new String(data, "UTF-8")) } } val doc = try { XML.load(new ByteArrayInputStream(data)) } catch { case e: SAXParseException => // save the tidy version... System.err.println("Could not parse the html markup: " + e.getMessage + " at " + e.getLineNumber + ":" + e.getColumnNumber) out.write(data) return case e: Throwable => // save the tidy version... System.err.println("Could not parse the html markup: " + e.getMessage) out.write(data) return } doc.child.foreach(process(_)) } if (to != null) { out = new IndentPrintStream(new FileOutputStream(to)) doit out.close() } else { out = new IndentPrintStream(session.getConsole) doit out.flush() } null } def to_text(line: String): String = { line } def to_element(tag: String): String = { var rc = tag if (rc.startsWith("div.") || tag.startsWith("div#")) { rc = rc.stripPrefix("div") } "%" + rc } def process(value: AnyRef): Unit = { val t = out import t._ def tag(name: String) = { if (name.matches("""^[\w:_\-]+$""")) { name } else { "'" + name + "'" } } value match { case x: Elem => var id = "" var clazz = "" var atts = "" def add(key: String, value: String) = { if (atts != "") { atts += " " } atts += key + "=\"" + value + "\"" } x.attributes.foreach { a => val key = a.key val value = a.value.toString if (key == "id") { if (value.matches("""^[\w_\-]+$""")) id = "#" + value else add(key, value) } else if (key == "class") { if (value.matches("""^[\w\s_\-]+$""")) { value.split("""\s""").foreach { c => clazz += "." + c } } else { add(key, value) } } else { add(key, value) } } if (x.label == "scriptlet") { for (line <- x.child.text.trim().split("""\r?\n""").filter(_.length() != 0)) { pi.pl("- " + line) } } else { pi.p(to_element(tag(x.label) + id + clazz)) if (atts != "") { p("(" + atts + ")") } x.child match { case Seq(x: Text) => val value = x.text.trim if (value.contains("\n")) { pl() indent { process(x) } } else { pl(" " + value) } case x => pl() indent { x.foreach { process _ } } } } case x: Text => val value = x.text.trim value.split("\r?\n").map(_.trim).foreach { line => if (line != "") { pi.pl(to_text(line)) } } case x: AnyRef => throw new Exception("Unhandled type: " + x.getClass); } } class IndentPrintStream(out: OutputStream) extends PrintStream(out) { var level = 0 def indent[T](op: => T): T = { level += 1; val rc = op; level -= 1; rc } def pi = { for (i <- 0 until level) { print(" ") }; this } def p(line: String) = { print(line); this } def pl(line: String = "") = { println(line); this } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy