Coder Social home page Coder Social logo

xsbt-scalate-generate's Introduction

Scalate support for SBT 0.1x.x

Integration for SBT that lets you generate sources for your Scalate templates and precompile them as part of the normal compilation process. This plugin is published to scala-tools.org.

Usage

Getting the plugin

Include the plugin in project/plugins.sbt:

For sbt 0.12.x, 0.13.x:

addSbtPlugin("com.mojolly.scalate" % "xsbt-scalate-generator" % "0.5.0")

For sbt 0.11.3:

resolvers += Resolver.url("sbt-plugin-releases",
  new URL("http://scalasbt.artifactoryonline.com/scalasbt/sbt-plugin-releases/"))(
    Resolver.ivyStylePatterns)

addSbtPlugin("com.mojolly.scalate" % "xsbt-scalate-generator" % "0.2.0")

for sbt 0.11.2: (maven central)

libraryDependencies <+= sbtVersion(v => "com.mojolly.scalate" %% "xsbt-scalate-generator" % (v + "-0.1.6"))

or as a git dependency in project/project/build.scala:

import sbt._
import Keys._

object PluginsBuild extends Build {
  lazy val root = Project("plugins", file(".")) dependsOn (scalateGenerate) settings (scalacOptions += "-deprecation")
  lazy val scalateGenerate = ProjectRef(uri("git://github.com/mojolly/xsbt-scalate-generate.git"), "xsbt-scalate-generator")
}

Configuring the plugin in build.sbt

Configure the plugin in build.sbt:

import ScalateKeys._

seq(scalateSettings:_*)
      
// Scalate Precompilation and Bindings
scalateTemplateConfig in Compile <<= (sourceDirectory in Compile){ base =>
  Seq(
    TemplateConfig(
      base / "webapp" / "WEB-INF" / "webTmpl",
      Seq(
        "import org.myapp.scalate.Helpers._",
        "import org.myapp.model._",
        "import net.liftweb.common._",
        "import org.joda.time._",
        "import org.scalatra.UrlGenerator"
      ),
      Seq(
        Binding("context", "_root_.org.scalatra.scalate.ScalatraRenderContext", importMembers = true, isImplicit = true),
        Binding("messageTranslatorModel", "org.myapp.model.mongo.MessageTranslator", importMembers = true, isImplicit = true, defaultValue = null),
        Binding("userSession", "org.myapp.auth.UserSession", importMembers = true, defaultValue = null),
        Binding("env", "org.myapp.util.Environment")
      ),
      Some("webTmpl")
    ),
    TemplateConfig(
      base / "webapp" / "WEB-INF" / "mailTmpl",
      Seq(
        "import org.myapp.scalate.Helpers._",
        "import org.myapp.model._",
        "import net.liftweb.common._",
        "import org.joda.time._"
      ),
      Seq(
        Binding("i18n", "org.myapp.model.mongo.MessageTranslator", true, isImplicit = true, defaultValue = null),
        Binding("user", "User", false, defaultValue = null),
        Binding("config", "com.typesafe.config.Config", false, defaultValue = null),
        Binding("assets", "org.myapp.model.mongo.fields.AssetPaths", false, isImplicit = true, defaultValue = null),
        Binding("geonames", "org.myapp.model.Geonames", false, isImplicit = true, defaultValue = null)
      ),
      Some("mailTmpl")
    )
  )
}

Configuring the plugin in project/build.scala

Configure the plugin in project/build.scala:

import sbt._
import sbt.Keys._
import com.mojolly.scalate.ScalatePlugin._
import ScalateKeys._

object build extends Build {  
  val templateSettings = scalateSettings ++ Seq(
    /**
     * Sets the behavior of recompiling template files.
     * Always template files are recompiled when this setting is true.
     * When you set it to false, they are recompiled only when the modified time of
     * a template file is newer than that of a scala file generated by compilation
     * or a compiled scala file corresponding to a template file doesn't exist yet.
     */
    scalateOverwrite := true,
    scalateTemplateConfig in Compile <<= (baseDirectory) { base =>
      Seq(
        /**
         * A minimal template configuration example.
         * "scalate" is used as a package prefix(the 4th argument of TemplateConfig.apply)
         * if not specified.
         *
         * An example of a scalate usage is as bellow if you have templates/index.ssp.
         *
         * val engine = new TemplateEngine
         * engine.layout("/scalate/index.ssp")
         */
        TemplateConfig(
          base / "templates",
          Nil,
          Nil
        )
      )
    }
  )

  lazy val root = Project("root", file(".")).settings(templateSettings:_*)
}

Trigger recompilation on save

From version 0.2.2 onwards the plugin detects when sources are changed and will trigger a recompilation. Older versions can add this to their build.sbt:

watchSources <++= (scalateTemplateDirectory in Compile) map (d => (d ** "*").get)

To use multiiple template directories with scalatra you'll need to make some changes too:

trait YourScalateSupport extends ScalateSupport {
 
  override protected def defaultTemplatePath: List[String] = List("/webTmpl/views")
 
  override protected def createTemplateEngine(config: ConfigT) = {
    val engine = super.createTemplateEngine(config)
 
    engine.layoutStrategy = new DefaultLayoutStrategy(engine,
      TemplateEngine.templateTypes.map("/webTmpl/layouts/default." + _): _*)
 
    engine.packagePrefix = "webTmpl"
    engine
  }
 
}

Patches

Patches are gladly accepted from their original author. Along with any patches, please state that the patch is your original work and that you license the work to the xsbt-scalate-generate project under the MIT License.

License

MIT licensed. Check the LICENSE file.

xsbt-scalate-generate's People

Contributors

bowlingx avatar casualjim avatar fizbin avatar ngocdaothanh avatar sdb avatar seratch avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

xsbt-scalate-generate's Issues

ClassLoader issue when trying to compile

When attempting to compile using xsbt-scalate-generate I get the following error. It seems the issue is that com.mojolly.scalate.Generator never ends up in the runtime path, no idea why this is happening because the code is exactly the same as the g8 scalatra template

[trace] Stack trace suppressed: run last compile:managedSources for the full output.
[error] (compile:managedSources) java.lang.ClassNotFoundException: com.mojolly.scalate.Generator

With the stack trace as follows

java.lang.ClassNotFoundException: com.mojolly.scalate.Generator
        at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
        at com.mojolly.scalate.ScalatePlugin$$anonfun$generateScalateSource$1$$anonfun$apply$1.apply(ScalatePlugin.scala:76)
        at com.mojolly.scalate.ScalatePlugin$$anonfun$generateScalateSource$1$$anonfun$apply$1.apply(ScalatePlugin.scala:73)
        at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:251)
        at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:251)
        at scala.collection.immutable.List.foreach(List.scala:318)
        at scala.collection.TraversableLike$class.flatMap(TraversableLike.scala:251)
        at scala.collection.AbstractTraversable.flatMap(Traversable.scala:105)
        at com.mojolly.scalate.ScalatePlugin$$anonfun$generateScalateSource$1.apply(ScalatePlugin.scala:73)
        at com.mojolly.scalate.ScalatePlugin$$anonfun$generateScalateSource$1.apply(ScalatePlugin.scala:72)
        at com.mojolly.scalate.ScalatePlugin$.withScalateClassLoader(ScalatePlugin.scala:129)
        at com.mojolly.scalate.ScalatePlugin$.generateScalateSource(ScalatePlugin.scala:72)
        at com.mojolly.scalate.ScalatePlugin$$anonfun$scalateSourceGeneratorTask$1.apply(ScalatePlugin.scala:52)
        at com.mojolly.scalate.ScalatePlugin$$anonfun$scalateSourceGeneratorTask$1.apply(ScalatePlugin.scala:52)
        at scala.Function6$$anonfun$tupled$1.apply(Function6.scala:35)
        at scala.Function6$$anonfun$tupled$1.apply(Function6.scala:34)
        at scala.Function1$$anonfun$compose$1.apply(Function1.scala:47)
        at sbt.$tilde$greater$$anonfun$$u2219$1.apply(TypeFunctions.scala:42)
        at sbt.std.Transform$$anon$4.work(System.scala:64)
        at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:237)
        at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:237)
        at sbt.ErrorHandling$.wideConvert(ErrorHandling.scala:18)
        at sbt.Execute.work(Execute.scala:244)
        at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:237)
        at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:237)
        at sbt.ConcurrentRestrictions$$anon$4$$anonfun$1.apply(ConcurrentRestrictions.scala:160)
        at sbt.CompletionService$$anon$2.call(CompletionService.scala:30)
        at java.util.concurrent.FutureTask.run(FutureTask.java:262)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
        at java.util.concurrent.FutureTask.run(FutureTask.java:262)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:744)

This is my plugins.sbt

addSbtPlugin("com.mojolly.scalate" % "xsbt-scalate-generator" % "0.4.2")

addSbtPlugin("org.scalatra.sbt" % "scalatra-sbt" % "0.3.2")

And this is the config (which is the default scalatra config)

      scalateTemplateConfig in Compile <<= (sourceDirectory in Compile){ base =>
        Seq(
          TemplateConfig(
            base / "webapp" / "WEB-INF" / "templates",
            Seq.empty,  /* default imports should be added here */
            Seq(
              Binding("context", "_root_.org.scalatra.scalate.ScalatraRenderContext", importMembers = true, isImplicit = true)
            ),  /* add extra bindings here */
            Some("templates")
          )
        )
      }

Support for sbt 0.13

sbt 0.13.0-RC4 was recently released. In trying to test it out on our project, the only plugin that does not yet support sbt 0.13 is xsbt-scalate-generate. It would be great if we could get support for it before the sbt 0.13.0 final release.

Updare README about 0.5.1

I see that v0.5.1 has been released:
https://github.com/backchatio/xsbt-scalate-generate/releases

But README is still saying:
addSbtPlugin("com.mojolly.scalate" % "xsbt-scalate-generator" % "0.5.0")

One more thing, when I change 0.5.0 above to 0.5.1, SBT can't find the new version:
[error] (*:update) sbt.ResolveException: unresolved dependency: com.mojolly.scalate#xsbt-scalate-generator;0.5.1: not found

Build for Scala 2.10.0

Thank you for #9.

Scalate has been built for Scala 2.10.0.

Because Scala 2.10.x are binary compatible and Scala 2.10.0 final will be released very very soon:
https://groups.google.com/forum/#!topic/scala-internals/3R7xTJhcN0I%5B1-25-false%5D
many libs I know have already released builds for it. You can release for Scala 2.10.0 without problem.

I'm asking for this build because my framework (http://ngocdaothanh.github.com/xitrum/) depends on xsbt-scalate-generate and I want to release a build for Scala 2.10.0.

Thanks.

Support Scala special keywords in file path

During compilation, template file path will become part of the package name of the generated class. Consequently, the compilation fails if, for example, the file path contains "private" string.

/private/var/folders/mk/lknymby579qcj5_wx8js461h0000gr/T/scalate-8516439701475108219-workdir/src/var/folders/mk/lknymby579qcj5_wx8js461h0000gr/T/tmp8554675948254167709.jade.scala:2: error: identifier expected but 'var' found.
package var.folders.mk.lknymby579qcj5_wx8js461h0000gr.T
        ^
        one error found

source generation task changes Logback configuration and doesn't change it back

In ScalatePlugin.generateScalateSource, you're doing this--

System.setProperty("logback.configurationFile", logConfig.toString)

-- where, by default, logConfig is the current project directory plus "src/main/resources/logback.xml". However, the property never gets cleared after the task runs.

The result is that if you also have a logback-test.xml, which Logback is supposed to use preferentially, it'll be ignored and you'll waste some time wondering why it keeps insisting on using your production logging settings in a development environment. My workaround has been to add a hook to the compile task (compile andFinally { System.clearProperty("logback.configurationFile"); }), and I guess I could also calculate the absolute path to my logback-test.xml file and set scalateLoggingConfig to that, but I don't think either should be necessary -- the task is just not behaving well here.

Source filename not shown in error messages

I get error messages like:

org.fusesource.scalate.InvalidSyntaxException: string matching regex `[a-zA-Z_0-9][a-zA-Z_0-9-]*' expected but `
[error] ' found at 35.18

OK so I'm pretty sure that's line 35 - but in which file?

When included with ScalaPB, I get "is already defined as" error.

Do you know why?

scalapb/ScalaPB#181

examples > sbt compile
[info] Loading global plugins from /Users/rjonna/.sbt/0.13/plugins
[info] Loading project definition from /Users/rjonna/source/play/grpc/ScalaPB/examples/project
[info] Set current project to examples (in build file:/Users/rjonna/source/play/grpc/ScalaPB/examples/)
[info] Compiling Templates in Template Directory: /Users/rjonna/source/play/grpc/ScalaPB/examples/src/main/resources/templates
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
[info] Compiling 9 Scala sources to /Users/rjonna/source/play/grpc/ScalaPB/examples/target/scala-2.11/classes...
[error] /Users/rjonna/source/play/grpc/ScalaPB/examples/target/scala-2.11/src_managed/main/scalate/templates/test_jade.scala:4**: $scalate$test_jade is already defined as object $scalate$test_jade**
[error] object $scalate$test_jade {
[error] ^
[error] /Users/rjonna/source/play/grpc/ScalaPB/examples/target/scala-2.11/src_managed/main/scalate/templates/test_jade.scala:18: $scalate$test_jade is already defined as class $scalate$test_jade
[error] class $scalate$test_jade extends root.org.fusesource.scalate.Template {
[error] ^
[error] two errors found
error Compilation failed
[error] Total time: 1 s, completed Oct 19, 2016 3:18:22 PM

Some source files don't have package statements

With sbt 0.11.3 and xsbt-scalate-generate 0.2.0, some generated scala files are generated in the default package (i.e. there is no package statement), and I've just experienced this with two of them, both of them called index.scaml. As you might imagine, this leads to the following compilation errors:

$_scalate_$index_scaml is already defined as object $_scalate_$index_scaml
[error] object $_scalate_$index_scaml {
[error]        ^
[...]/index_scaml.scala:46: $_scalate_$index_scaml is already defined as class
$_scalate_$index_scaml
[error] class $_scalate_$index_scaml extends _root_.org.fusesource.scalate.Template {
[error]       ^
[error] two errors found

This is really bizarre because I can't see how this could even work at runtime.

Not working with Scala 2.9.2

I am trying to use xsbt-scalate-generate in a 2.9.2 project. Since it is currently not cross-built against that version of scala, I forked the project, added 2.9.2 as the scala version and tried to use my fork as a git dependency. However, sbt keeps complaining about the following dependency.

[info] Resolving com.mojolly.scalate#scalate-generator_2.9.2;0.1.7 ...

What I don't understand is that this dependency is part of the xsbt-scalate-project, so I would expect that it is resolved correctly when the project build is updated to 2.9.2.

I fixed the issue by locally publishing the project. Then all dependencies are resolved correctly. Any ideas why it doesn't work properly as a git depdency?

mighty familiar

Looks like you copied a lot from my xsbt-scalate-precompiler-plugin. Lots of similar names and so on.

Normally, I'd request some sort of credit for this, but I'm mostly interested in what improvements you made?

I'd totally be willing to just shut down my version because I don't use Scala much any more, but it might have been nice to be notified or asked or something!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.