1
0

Display dependency fragments

This commit is contained in:
Hubert Van De Walle 2020-10-06 15:27:38 +02:00
parent f56ec93498
commit a856d5e425
8 changed files with 166 additions and 44 deletions

View File

@ -1,7 +1,8 @@
module.exports = {
purge: {
content: [
'../main/resources/views/**/*.twig'
'../main/resources/views/**/*.twig',
'../main/kotlin/starter/PebbleModule.kt',
]
},
theme: {},

View File

@ -1,5 +1,7 @@
package starter
import org.http4k.core.then
import org.http4k.filter.ServerFilters
import org.http4k.routing.ResourceLoader
import org.http4k.routing.RoutingHttpHandler
import org.http4k.routing.routes
@ -25,9 +27,8 @@ val mainModule = module {
} onClose { it?.stop() }
single { Config().load() }
single { PebbleModule().engine() }
single { LoggerFactory.getLogger("Starter") }
single { Views(get()) }
single { Views(get(), get()) }
single { ProjectZip(getAll()) }
}
@ -39,18 +40,19 @@ val templateModule = module {
}
val routesModule = module {
single { IndexRouteSupplier(get(), get()) } bind RouteSupplier::class
single { IndexRouteSupplier(get()) } bind RouteSupplier::class
single { ZipRouteSupplier(get(), get()) } bind RouteSupplier::class
single {
routes(
static(ResourceLoader.Classpath("/assets")),
getAll<RouteSupplier>().toRouter()
)
ServerFilters.CatchAll().then(
routes(
static(ResourceLoader.Classpath("/assets")),
getAll<RouteSupplier>().toRouter()
))
}
}
fun main() {
startKoin {
modules(mainModule, templateModule, routesModule)
modules(mainModule, pebbleModule, templateModule, routesModule)
}
}

View File

@ -1,15 +1,57 @@
package starter
import com.mitchellbosecke.pebble.PebbleEngine
import com.mitchellbosecke.pebble.loader.ClasspathLoader
import com.mitchellbosecke.pebble.extension.escaper.SafeString
import com.mitchellbosecke.pebble.template.EvaluationContext
import com.mitchellbosecke.pebble.template.PebbleTemplate
import org.intellij.lang.annotations.Language
import org.koin.dsl.bind
import org.koin.dsl.module
import starter.utils.PebbleEngineBuilder
import starter.utils.PebbleEngineBuilder.CacheType.ConcurrentMap
import starter.utils.PebbleFunction
class PebbleModule {
fun engine(): PebbleEngine {
val loader = ClasspathLoader()
loader.suffix = ".twig"
return PebbleEngine.Builder()
.loader(loader)
.cacheActive(true)
.build()
class DepAsXmlPebbleFunction : PebbleFunction {
override val name = "depAsXml"
override fun getArgumentNames() = listOf("dependency")
override fun execute(args: Map<String, Any>, self: PebbleTemplate, context: EvaluationContext, lineNumber: Int): Any {
val dep = args["dependency"] as Dependency
fun startTag(name: String): String {
@Language("html") @Suppress("UnnecessaryVariable")
val result = """<span class="text-gray-700">&lt;</span><span class="text-red-700">$name</span><span class="text-gray-700">&gt;</span>"""
return result
}
fun endTag(name: String): String {
@Language("html") @Suppress("UnnecessaryVariable")
val result = """<span class="text-gray-700">&lt;/</span><span class="text-red-700">$name</span><span class="text-gray-700">&gt;</span>"""
return result
}
fun tag(name: String, content: String): String {
return """${startTag(name)}$content${endTag(name)}"""
}
val result = """
|${startTag("dependency")}
| ${tag("groupId", dep.groupId)}
| ${tag("artifactId", dep.artifactId)}
| ${tag("version", dep.version)}
|${endTag("dependency")}
""".trimMargin()
return SafeString(result)
}
}
val pebbleModule = module {
single { DepAsXmlPebbleFunction() } bind PebbleFunction::class
single {
PebbleEngineBuilder {
cache = ConcurrentMap
functions(getAll())
classPath { suffix = ".twig" }
}
}
}

View File

@ -3,12 +3,11 @@ package starter
import com.mitchellbosecke.pebble.PebbleEngine
import starter.utils.render
class Views(private val engine: PebbleEngine) {
fun index(dependencies: List<Dependency>, inputs: List<Input>): String {
val dependenciesByCategory = dependencies.groupBy { it.category }.toSortedMap()
return engine.render(
"views/index",
mapOf("dependencies" to dependenciesByCategory, "inputs" to inputs)
)
}
class Views(private val engine: PebbleEngine, config: StarterConfig) {
private val args = mapOf(
"dependencies" to config.dependencies.groupBy { it.category }.toSortedMap(),
"inputs" to config.inputs
)
fun index() = engine.render("views/index", args)
}

View File

@ -7,13 +7,10 @@ import org.http4k.routing.bind
import starter.StarterConfig
import starter.Views
class IndexRouteSupplier(
private val views: Views,
private val conf: StarterConfig,
) : RouteSupplier {
class IndexRouteSupplier(private val views: Views) : RouteSupplier {
override fun get() = "/" bind Method.GET to {
Response(Status.OK)
.body(views.index(conf.dependencies, conf.inputs))
.body(views.index())
.header("Content-Type", "text/html")
}
}

View File

@ -1,11 +1,87 @@
package starter.utils
import com.mitchellbosecke.pebble.PebbleEngine
import com.mitchellbosecke.pebble.cache.tag.CaffeineTagCache
import com.mitchellbosecke.pebble.cache.tag.ConcurrentMapTagCache
import com.mitchellbosecke.pebble.cache.tag.NoOpTagCache
import com.mitchellbosecke.pebble.cache.template.CaffeineTemplateCache
import com.mitchellbosecke.pebble.cache.template.ConcurrentMapTemplateCache
import com.mitchellbosecke.pebble.cache.template.NoOpTemplateCache
import com.mitchellbosecke.pebble.extension.AbstractExtension
import com.mitchellbosecke.pebble.extension.Filter
import com.mitchellbosecke.pebble.extension.Function
import com.mitchellbosecke.pebble.loader.ClasspathLoader
import java.io.StringWriter
fun PebbleEngine.render(name: String, args: Map<String, Any?> = mapOf()): String {
val template = getTemplate(name)
val writer = StringWriter()
template.evaluate(writer, args)
return writer.toString()
fun PebbleEngine.render(name: String, args: Map<String, Any?> = mapOf()) =
getTemplate(name).let { StringWriter().apply { it.evaluate(this, args) }.toString() }
fun PebbleEngine.render(name: String, vararg args: Pair<String, Any?>) =
render(name, mapOf(*args))
interface PebbleFunction : Function {
val name: String
}
interface PebbleFilter : Filter {
val name: String
}
class PebbleEngineBuilder {
enum class CacheType {
None, Caffeine, ConcurrentMap
}
private var loader = ClasspathLoader()
var cache = CacheType.ConcurrentMap
private val functions = mutableListOf<PebbleFunction>()
private val filters = mutableListOf<PebbleFilter>()
fun function(function: PebbleFunction) {
functions.add(function)
}
fun functions(functions: Iterable<PebbleFunction>) {
this.functions.addAll(functions)
}
fun filter(filter: PebbleFilter) {
filters.add(filter)
}
fun filters(filters: Iterable<PebbleFilter>) {
this.filters.addAll(filters)
}
fun classPath(block: ClasspathLoader.() -> Unit) {
loader = ClasspathLoader().apply(block)
}
companion object {
operator fun invoke(block: PebbleEngineBuilder.() -> Unit): PebbleEngine =
PebbleEngineBuilder().apply(block).let { builder ->
PebbleEngine.Builder()
.loader(builder.loader)
.cacheActive(builder.cache != CacheType.None)
.templateCache(when (builder.cache) {
CacheType.None -> NoOpTemplateCache()
CacheType.Caffeine -> CaffeineTemplateCache()
CacheType.ConcurrentMap -> ConcurrentMapTemplateCache()
})
.tagCache(when (builder.cache) {
CacheType.None -> NoOpTagCache()
CacheType.Caffeine -> CaffeineTagCache()
CacheType.ConcurrentMap -> ConcurrentMapTagCache()
})
.extension(object : AbstractExtension() {
override fun getFunctions(): Map<String, Function>? =
builder.functions.associateBy { it.name }.ifEmpty { null }
override fun getFilters(): Map<String, Filter>? =
builder.filters.associateBy { it.name }.ifEmpty { null }
})
.build()
}
}
}

File diff suppressed because one or more lines are too long

View File

@ -1,9 +1,14 @@
{% macro dependency(dependency) %}
<label class="m-2">
<input name="{{ dependency.name }}"
type="checkbox"{% if dependency.default %} checked{% endif %}>
<span>{{ dependency.name }}</span>
</label>
<details>
<summary>
<label class="m-2">
<input name="{{ dependency.name }}"
type="checkbox"{% if dependency.default %} checked{% endif %}>
<span>{{ dependency.name }}</span>
</label>
</summary>
<pre><code>{{ depAsXml(dependency) }}</code></pre>
</details>
{% endmacro %}
{% macro input(input) %}
@ -17,4 +22,4 @@
<input name="{{ input.name }}" id="{{ input.name }}" class="input"{% if input.value %} value="{{ input.value }}"{% endif %}>
</div>
</div>
{% endmacro %}
{% endmacro %}