Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How would one compile Twirl templates? #48

Open
nafg opened this issue Aug 20, 2019 · 19 comments
Open

How would one compile Twirl templates? #48

nafg opened this issue Aug 20, 2019 · 19 comments

Comments

@nafg
Copy link
Contributor

nafg commented Aug 20, 2019

I think that what needs to happen is for something to pull in https://mvnrepository.com/artifact/com.typesafe.play/twirl-compiler_2.12/1.4.2 and call https://github.com/playframework/twirl/blob/master/compiler/src/main/scala/play/twirl/compiler/TwirlCompiler.scala#L177 ?

@tindzk
Copy link
Owner

tindzk commented Aug 20, 2019

You could write a small wrapper class that calls TwirlCompiler.compile(). Then, you can reference it in your build as follows:

[module.twirl.jvm]
root = "twirl"
sources = "twirl/src/"
scalaDeps = [["com.typesafe.play", "twirl-compiler", "1.4.2"]]

[module.templates.target.html]
root  = "templates"
class = { module = "twirl:jvm", main = "twirl.TwirlWrapper" }
await = true

@nafg
Copy link
Contributor Author

nafg commented Aug 20, 2019 via email

@nafg
Copy link
Contributor Author

nafg commented Aug 20, 2019 via email

@nafg
Copy link
Contributor Author

nafg commented Aug 20, 2019

I see there's also MODULE_PATH but it's also based on the root project. I don't see any way to get which module it's being invoked for (and its path).

@tindzk
Copy link
Owner

tindzk commented Aug 21, 2019

$MODULE_PATH is used for accessing or creating source files, whereas $BUILD_PATH is for generated assets (JavaScript, CSS) that your application needs during runtime.

$MODULE_PATH is based on the project the build target is part of, which is not necessarily the root project. For example, your build file might import another build from a different folder which contains a custom target.

I am not sure we can introduce an additional environment variable that points to the module path the target is being invoked for. The reason is that the source generator can be run in isolation:

seed build templates:html

You can have a look at this example which is similar to what you are trying to do. The generator script is part of utils. It creates a Scala file in the source directory of the demo module. You could do the same and exclude the generated files in your .gitignore.

@nafg
Copy link
Contributor Author

nafg commented Aug 21, 2019

I saw that, but this is not a realistic approach when I have multiple modules with twirl templates.

@tindzk
Copy link
Owner

tindzk commented Aug 22, 2019

I see. We could change the semantics of the $MODULE_PATH environment variable such that if we have the following build target:

[module.templates.target.html]
root  = "templates"
class = { module = "twirl:jvm", main = "twirl.TwirlWrapper" }
await = true

$MODULE_PATH would point to the module's root path. If the root path is not set, the $MODULE_PATH environment variable would not be defined either.

Additionally, we can introduce $PROJECT_PATH that will inherit the current behaviour of $MODULE_PATH.

@nafg
Copy link
Contributor Author

nafg commented Aug 22, 2019 via email

@tindzk
Copy link
Owner

tindzk commented Aug 22, 2019

No, you do not necessarily have to hard-code any paths in TwirlWrapper. It could compile all Twirl files in $MODULE_PATH/ to $MODULE_PATH/generated.

I am not sure how useful the notion of generated sources would be since you can already pass in multiple paths to the sources setting. Here is a full example of how I envision it to work:

[module.shop.jvm]
sources = ["shop/src/", "shop/twirl/generated/"]

[module.shop.target.html]
root = "shop/twirl/"
class = ["twirl:jvm", "twirl.TwirlWrapper"]
await = true

[module.dashboard.jvm]
sources = ["dashboard/src/", "dashboard/twirl/generated/"]

[module.dashboard.target.html]
root = "dashboard/twirl/"
class = ["twirl:jvm", "twirl.TwirlWrapper"]
await = true

@nafg
Copy link
Contributor Author

nafg commented Aug 22, 2019 via email

@tindzk
Copy link
Owner

tindzk commented Aug 22, 2019

Note that in my example from above I only set the root path on the custom build target. You can additionally set it on the JVM module. Here is how your particular example could look like:

[module.viewsCommon.jvm]
root = "views_common/"
sources = ["views_common/src/main/scala/", "views_common/target/"]

[module.viewsCommon.target.html]
root = "views_common/src/main/twirl/"
class = ["twirl:jvm", "twirl.TwirlWrapper"]
await = true

If the paths of your modules follow the same convention, your wrapper class could compile $MODULE_PATH/ to $MODULE_PATH/../../target/.

@nafg
Copy link
Contributor Author

nafg commented Dec 11, 2019

This isn't working. I'm still not getting the path of the module that's invoking the class in MODULE_PATH.

@nafg
Copy link
Contributor Author

nafg commented Dec 12, 2019

I see that if I move the viewsCommon stuff into views_common/build.toml and include it from the main build.toml, then $MODULE_PATH gets set to views_common and I can proceed. In that way I got some twirl to compile. However it is annoying to have to do that.

@nafg
Copy link
Contributor Author

nafg commented Dec 12, 2019

How can I get --watch to include changes to templates without seed going and passing them to scalac?

@tindzk
Copy link
Owner

tindzk commented Dec 16, 2019

I see that if I move the viewsCommon stuff into views_common/build.toml and include it from the main build.toml, then $MODULE_PATH gets set to views_common and I can proceed. In that way I got some twirl to compile. However it is annoying to have to do that.

Yes, correct. I will introduce another environment variable that will refer to the path of the invoked module (if available).

How can I get --watch to include changes to templates without seed going and passing them to scalac?

I am not sure I understood you. Do you want to run your script to convert Twirl templates to Scala, but not compile the files afterwards?

@nafg
Copy link
Contributor Author

nafg commented Dec 16, 2019

Yes, correct. I will introduce another environment variable that will refer to the path of the invoked module (if available).

More broadly, it would be great if I could get the entire config somehow (e.g. see #72 bullet 4).

I am not sure I understood you. Do you want to run your script to convert Twirl templates to Scala, but not compile the files afterwards?

I mean if I make a change to a .scala.html file it should run the .target.twirl target, even though src/main/twirl isn't in the .jvm module's sources.

@tindzk
Copy link
Owner

tindzk commented Dec 16, 2019

I mean if I make a change to a .scala.html file it should run the .target.twirl target, even though src/main/twirl isn't in the .jvm module's sources.

I see. As you noticed, the --watch parameter is ignored on class-based build targets. We could set up a file watcher for all files in root or introduce a separate setting, e.g. watchPaths. Whenever a file is changed, it would re-run your Twirl code generator. The reason I was hesitant about implementing this was that the JVM incurs a startup penalty which would be undesirable in your use case. It would be more efficient to do the file watching from within your Twirl wrapper, e.g. using the directory-watcher library.

@nafg
Copy link
Contributor Author

nafg commented Dec 16, 2019

It would be more efficient to do the file watching from within your Twirl wrapper, e.g. using the directory-watcher library.

But then it would have to be async, and wouldn't that make Seed not know when to compile the resulting .template.scala files?

@tindzk
Copy link
Owner

tindzk commented Dec 17, 2019

Yes, it would have to be running in the background. Seed already sets up file watchers for all source paths. Since the viewsCommon module lists the target path for the generated Twirl templates (views_common/target/), Seed should detect any new or changed files, compile them and restart the application.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants