Created
March 22, 2023 18:03
-
-
Save nedtwigg/21ed9275b4ba9cdb89e0029abc60e2e2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package common | |
import gg.jte.TemplateEngine | |
import gg.jte.TemplateOutput | |
// you need to define this interface yourself. It needs to have the render method, | |
// and you can add other methods if you want | |
interface JteModel { | |
fun render(engine: TemplateEngine, output: TemplateOutput) | |
} | |
// JteModelPlugin then generates code that looks like this | |
class main( | |
val title: String, | |
val description: String, | |
val content: gg.jte.Content, | |
) : common.JteModel { | |
override fun render(engine: TemplateEngine, output: TemplateOutput) { | |
engine.render("pages/main.jte", mapOf( | |
"title" to title, | |
"description" to description, | |
"content" to content, | |
), output) | |
} | |
} | |
class aboutUs( | |
) : common.JteModel { | |
override fun render(engine: TemplateEngine, output: TemplateOutput) { | |
engine.render("pages/Marketing/aboutUs.jte", mapOf( | |
), output) | |
} | |
} | |
// to pass data into the templates without arguments, you can use thread locals like this | |
object JteCtx { | |
class Module : Jooby.Module { | |
override fun configure(env: Env, conf: Config, binder: Binder) { | |
Multibinder.newSetBinder(binder, org.jooby.Renderer::class.java) | |
.addBinding() | |
.toInstance(Jte()) | |
} | |
} | |
class Jte : org.jooby.Renderer { | |
override fun render(value: Any, ctx: org.jooby.Renderer.Context) { | |
if (value is JteModel) { | |
locals.set(ctx.locals()) | |
val output = Utf8ByteOutput() | |
val codeResolver = DirectoryCodeResolver(Paths.get("src/main/jte")) | |
val templateEngine = TemplateEngine.create(codeResolver, ContentType.Html) | |
value.render(templateEngine, output) | |
val buffer = ByteArrayOutputStream() | |
output.writeTo { bytes, offset, length -> buffer.write(bytes, offset, length) } | |
ctx.type(MediaType.html).length(output.contentLength.toLong()).send(buffer.toByteArray()) | |
} | |
} | |
} | |
val locals = ThreadLocal.withInitial { mapOf<String, Any>() } | |
@JvmStatic | |
fun fp(input: String): String { | |
val fingerprinted = locals.get().get(CustomAssets._PERMANENT) as Map<String, String>? | |
return if (fingerprinted == null) { | |
CustomAssets.ASSETS_FINGERPRINT_RAW + input | |
} else { | |
val fp = fingerprinted[input] ?: throw NoSuchElementException("No such fingerprinted $input") | |
CustomAssets.ASSETS + "/permanent/" + fp | |
} | |
} | |
@JvmStatic | |
fun style(fileset: String): RockerRaw { | |
var threadLocals = locals.get() | |
val linkTags = | |
(threadLocals.get(fileset + CustomAssets._STYLES) | |
?: throw NoSuchElementException( | |
"No such styles $fileset, available: $threadLocals.keys")) | |
as String | |
return RockerRaw.raw(linkTags) | |
} | |
@JvmStatic | |
fun script(fileset: String): RockerRaw { | |
var threadLocals = locals.get() | |
val linkTags = | |
(threadLocals.get(fileset + CustomAssets._SCRIPTS) | |
?: throw NoSuchElementException( | |
"No such scripts $fileset, available: ${threadLocals.keys}")) | |
as String | |
return RockerRaw.raw(linkTags) | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is example output from
JteModelPlugin
which is listed at this gist.casid/jte#205 for further context.