From c5f94ef738af31f2716de41da021c437fb5fe274 Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Sat, 19 Aug 2017 11:45:27 -0400 Subject: [PATCH] Refactor TemplateEnvironment, add support for classpath templates --- .gitignore | 1 + build.gradle | 3 + src/main/kotlin/net/shadowfacts/ekt/EKT.kt | 108 +++++++++++++++--- .../services/javax.script.ScriptEngineFactory | 2 +- src/test/kotlin/net/shadowfacts/ekt/Test.kt | 2 +- .../resources/templates/includes/include.ekt | 5 + src/test/resources/templates/template.ekt | 7 ++ 7 files changed, 109 insertions(+), 19 deletions(-) create mode 100644 src/test/resources/templates/includes/include.ekt create mode 100644 src/test/resources/templates/template.ekt diff --git a/.gitignore b/.gitignore index 0fefdc4..d466e60 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ /.gradle # idea +/classes /out /run /.idea diff --git a/build.gradle b/build.gradle index abddb64..2ea3a48 100644 --- a/build.gradle +++ b/build.gradle @@ -8,6 +8,7 @@ buildscript { } plugins { + id "idea" id "maven" } @@ -23,6 +24,8 @@ dependencies { compile group: "org.jetbrains.kotlin", name: "kotlin-script-util", version: kotlin_version } +idea.module.inheritOutputDirs = true + uploadArchives { repositories.mavenDeployer { repository(url: "http://archiva.shadowfacts.net/repository/local/") { diff --git a/src/main/kotlin/net/shadowfacts/ekt/EKT.kt b/src/main/kotlin/net/shadowfacts/ekt/EKT.kt index 426a891..beed18e 100644 --- a/src/main/kotlin/net/shadowfacts/ekt/EKT.kt +++ b/src/main/kotlin/net/shadowfacts/ekt/EKT.kt @@ -27,9 +27,9 @@ object EKT { private val scriptPrefix = """ val _env = bindings["_env"] as net.shadowfacts.ekt.EKT.TemplateEnvironment val _result = StringBuilder() -fun echo(it: Any) { _result.append(it) } +fun echo(it: Any?) { _result.append(it) } fun include(include: String) { - val env = net.shadowfacts.ekt.EKT.TemplateEnvironment(include, _env) + val env = _env.createChild(include) echo(net.shadowfacts.ekt.EKT.render(env, env.include)) } """ @@ -80,20 +80,36 @@ _result.toString() return eval(script, env) } - fun render(name: String, templateDir: File, includeDir: File, cacheDir: File? = null, data: Map): String { - return render(TemplateEnvironment(name, templateDir, includeDir, cacheDir, data)) + fun renderFile(name: String, templateDir: File, includeDir: File, cacheDir: File? = null, data: Map): String { + return render(FileTemplateEnvironment(name, templateDir, includeDir, cacheDir, data)) } - fun render(name: String, templateDir: File, includeDir: File, cacheDir: File? = null, init: DataProvider.() -> Unit): String { - return render(TemplateEnvironment(name, templateDir, includeDir, cacheDir, init)) + fun renderFile(name: String, templateDir: File, includeDir: File, cacheDir: File? = null, init: DataProvider.() -> Unit): String { + return render(FileTemplateEnvironment(name, templateDir, includeDir, cacheDir, init)) } - fun render(name: String, dir: File, cacheScripts: Boolean = false, data: Map): String { - return render(name, dir, File(dir, "includes"), if (cacheScripts) File(dir, "cache") else null, data) + fun renderFile(name: String, dir: File, cacheScripts: Boolean = false, data: Map): String { + return renderFile(name, dir, File(dir, "includes"), if (cacheScripts) File(dir, "cache") else null, data) } - fun render(name: String, dir: File, cacheScripts: Boolean = false, init: DataProvider.() -> Unit): String { - return render(name, dir, File(dir, "includes"), if (cacheScripts) File(dir, "cache") else null, init) + fun renderFile(name: String, dir: File, cacheScripts: Boolean = false, init: DataProvider.() -> Unit): String { + return renderFile(name, dir, File(dir, "includes"), if (cacheScripts) File(dir, "cache") else null, init) + } + + fun renderClasspath(name: String, templatePath: String, includePath: String, cacheDir: File? = null, data: Map): String { + return render(ClasspathTemplateEnvironment(name, templatePath, includePath, cacheDir, data)) + } + + fun renderClasspath(name: String, templatePath: String, includePath: String, cacheDir: File? = null, init: DataProvider.() -> Unit): String { + return render(ClasspathTemplateEnvironment(name, templatePath, includePath, cacheDir, init)) + } + + fun renderClasspath(name: String, path: String, cacheDir: File? = null, data: Map): String { + return renderClasspath(name, path, "$path/includes", cacheDir, data) + } + + fun renderClasspath(name: String, path: String, cacheDir: File? = null, init: DataProvider.() -> Unit): String { + return renderClasspath(name, path, "$path/includes", cacheDir, init) } internal fun eval(script: String, env: TemplateEnvironment): String { @@ -112,22 +128,35 @@ _result.toString() return engine.eval(script) as String } - class TemplateEnvironment { - + interface TemplateEnvironment { val rootName: String val name: String - val templateDir: File - val includeDir: File val cacheDir: File? val data: Map val template: String - get() = File(templateDir, "$name.ekt").readText(Charsets.UTF_8) val include: String - get() = File(includeDir, "$name.ekt").readText(Charsets.UTF_8) val cacheFile: File get() = File(cacheDir!!, "$name.kts") + fun createChild(name: String): TemplateEnvironment + + } + + class FileTemplateEnvironment: TemplateEnvironment { + override val rootName: String + override val name: String + override val cacheDir: File? + override val data: Map + + val templateDir: File + val includeDir: File + + override val template: String + get() = File(templateDir, "$name.ekt").readText(Charsets.UTF_8) + override val include: String + get() = File(includeDir, "$name.ekt").readText(Charsets.UTF_8) + constructor(name: String, templateDir: File, includeDir: File, cacheDir: File?, data: Map) { this.rootName = name this.name = name @@ -140,7 +169,7 @@ _result.toString() constructor(name: String, templateDir: File, includeDir: File, cacheDir: File?, init: DataProvider.() -> Unit): this(name, templateDir, includeDir, cacheDir, DataProvider.init(init)) - constructor(name: String, parent: TemplateEnvironment, cacheDir: File? = parent.cacheDir) { + constructor(name: String, parent: FileTemplateEnvironment, cacheDir: File? = parent.cacheDir) { this.rootName = parent.rootName this.name = name this.templateDir = parent.templateDir @@ -149,6 +178,51 @@ _result.toString() this.data = parent.data } + override fun createChild(name: String): TemplateEnvironment { + return FileTemplateEnvironment(name, this) + } + + } + + class ClasspathTemplateEnvironment: TemplateEnvironment { + override val rootName: String + override val name: String + override val cacheDir: File? + override val data: Map + + val templatePath: String + val includePath: String + + override val template: String + get() = EKT::class.java.getResourceAsStream("$templatePath/$name.ekt").bufferedReader(Charsets.UTF_8).readText() + override val include: String + get() = EKT::class.java.getResourceAsStream("$includePath/$name.ekt").bufferedReader(Charsets.UTF_8).readText() + + constructor(name: String, templatePath: String, includePath: String, cacheDir: File?, data: Map) { + this.rootName = name + this.name = name + this.templatePath = templatePath + this.includePath = includePath + this.cacheDir = cacheDir + this.data = data + } + + constructor(name: String, templatePath: String, includePath: String, cacheDir: File?, init: DataProvider.() -> Unit): + this(name, templatePath, includePath, cacheDir, DataProvider.init(init)) + + constructor(name: String, parent: ClasspathTemplateEnvironment, cacheDir: File? = parent.cacheDir) { + this.rootName = parent.rootName + this.name = name + this.templatePath = parent.templatePath + this.includePath = parent.includePath + this.cacheDir = cacheDir + this.data = parent.data + } + + override fun createChild(name: String): TemplateEnvironment { + return ClasspathTemplateEnvironment(name, this) + } + } class DataProvider { diff --git a/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory b/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory index fa84d5e..f8f5900 100644 --- a/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory +++ b/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory @@ -1 +1 @@ -org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngineFactory +org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngineFactory \ No newline at end of file diff --git a/src/test/kotlin/net/shadowfacts/ekt/Test.kt b/src/test/kotlin/net/shadowfacts/ekt/Test.kt index 2b0e8aa..830bcdf 100644 --- a/src/test/kotlin/net/shadowfacts/ekt/Test.kt +++ b/src/test/kotlin/net/shadowfacts/ekt/Test.kt @@ -6,7 +6,7 @@ import java.io.File * @author shadowfacts */ fun main(args: Array) { - val res = EKT.render("template", File("."), cacheScripts = true) { + val res = EKT.renderClasspath("template", "/templates", cacheDir = File("cache")) { "list" to (listOf(1, 2, 3) asType "List") } diff --git a/src/test/resources/templates/includes/include.ekt b/src/test/resources/templates/includes/include.ekt new file mode 100644 index 0000000..a26e0d1 --- /dev/null +++ b/src/test/resources/templates/includes/include.ekt @@ -0,0 +1,5 @@ +--------- +Classpath include +[= list =] +My name is: [= _env.name =] +Root name: [= _env.rootName =] \ No newline at end of file diff --git a/src/test/resources/templates/template.ekt b/src/test/resources/templates/template.ekt new file mode 100644 index 0000000..a2d56e3 --- /dev/null +++ b/src/test/resources/templates/template.ekt @@ -0,0 +1,7 @@ +Environment type: [= _env::class.simpleName =] + +[= list.joinToString("\n") =] + +Sum: [= list.sum() =] + +[: include("include") :] \ No newline at end of file