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 = { module.exports = {
purge: { purge: {
content: [ content: [
'../main/resources/views/**/*.twig' '../main/resources/views/**/*.twig',
'../main/kotlin/starter/PebbleModule.kt',
] ]
}, },
theme: {}, theme: {},

View File

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

View File

@ -1,15 +1,57 @@
package starter package starter
import com.mitchellbosecke.pebble.PebbleEngine import com.mitchellbosecke.pebble.extension.escaper.SafeString
import com.mitchellbosecke.pebble.loader.ClasspathLoader 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 { class DepAsXmlPebbleFunction : PebbleFunction {
fun engine(): PebbleEngine { override val name = "depAsXml"
val loader = ClasspathLoader() override fun getArgumentNames() = listOf("dependency")
loader.suffix = ".twig" override fun execute(args: Map<String, Any>, self: PebbleTemplate, context: EvaluationContext, lineNumber: Int): Any {
return PebbleEngine.Builder() val dep = args["dependency"] as Dependency
.loader(loader)
.cacheActive(true) fun startTag(name: String): String {
.build() @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 com.mitchellbosecke.pebble.PebbleEngine
import starter.utils.render import starter.utils.render
class Views(private val engine: PebbleEngine) { class Views(private val engine: PebbleEngine, config: StarterConfig) {
fun index(dependencies: List<Dependency>, inputs: List<Input>): String { private val args = mapOf(
val dependenciesByCategory = dependencies.groupBy { it.category }.toSortedMap() "dependencies" to config.dependencies.groupBy { it.category }.toSortedMap(),
return engine.render( "inputs" to config.inputs
"views/index", )
mapOf("dependencies" to dependenciesByCategory, "inputs" to inputs)
) fun index() = engine.render("views/index", args)
}
} }

View File

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

View File

@ -1,11 +1,87 @@
package starter.utils package starter.utils
import com.mitchellbosecke.pebble.PebbleEngine 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 import java.io.StringWriter
fun PebbleEngine.render(name: String, args: Map<String, Any?> = mapOf()): String { fun PebbleEngine.render(name: String, args: Map<String, Any?> = mapOf()) =
val template = getTemplate(name) getTemplate(name).let { StringWriter().apply { it.evaluate(this, args) }.toString() }
val writer = StringWriter()
template.evaluate(writer, args) fun PebbleEngine.render(name: String, vararg args: Pair<String, Any?>) =
return writer.toString() 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) %} {% macro dependency(dependency) %}
<label class="m-2"> <details>
<input name="{{ dependency.name }}" <summary>
type="checkbox"{% if dependency.default %} checked{% endif %}> <label class="m-2">
<span>{{ dependency.name }}</span> <input name="{{ dependency.name }}"
</label> type="checkbox"{% if dependency.default %} checked{% endif %}>
<span>{{ dependency.name }}</span>
</label>
</summary>
<pre><code>{{ depAsXml(dependency) }}</code></pre>
</details>
{% endmacro %} {% endmacro %}
{% macro input(input) %} {% macro input(input) %}