Compare commits
13 Commits
00fec096cb
...
zip
| Author | SHA1 | Date | |
|---|---|---|---|
| 8ba3dac0b2 | |||
| ddf8558578 | |||
| 883610878a | |||
| 69e93f4def | |||
| 9365e8f0c5 | |||
| a4a30d1bea | |||
| 7f2256bcbb | |||
| cf46ec26c4 | |||
| 9fb5e43a0b | |||
| 7fc979053e | |||
| aaa7a63bfb | |||
| b0eaa16752 | |||
| 67e7a642db |
+13
-1
@@ -26,4 +26,16 @@ out/
|
||||
.idea_modules/
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
*.iws
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
|
||||
# yarn
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.yarn-integrity
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
+99
-1
@@ -1,19 +1,60 @@
|
||||
[inputs]
|
||||
|
||||
[inputs.name]
|
||||
default = "example"
|
||||
display = "Project Name"
|
||||
|
||||
[inputs.basePackage]
|
||||
default = "org.example"
|
||||
display = "Base package"
|
||||
|
||||
[inputs.javaVersion]
|
||||
default = "14"
|
||||
display = "Java Version"
|
||||
|
||||
[inputs.kotlinVersion]
|
||||
default = "1.4.10"
|
||||
display = "Kotlin Version"
|
||||
|
||||
[dependencies]
|
||||
|
||||
[dependencies.http4k]
|
||||
groupId = "org.http4k"
|
||||
artifactId = "http4k-core"
|
||||
version = "3.260.0"
|
||||
category = "server"
|
||||
default = true
|
||||
|
||||
[dependencies.http4k-server-jetty]
|
||||
groupId = "org.http4k"
|
||||
artifactId = "http4k-server-jetty"
|
||||
version = "3.260.0"
|
||||
category = "server"
|
||||
default = true
|
||||
|
||||
[dependencies.http4k-server-apache]
|
||||
groupId = "org.http4k"
|
||||
artifactId = "http4k-server-apache"
|
||||
version = "3.260.0"
|
||||
category = "server"
|
||||
|
||||
[dependencies.http4k-client-apache]
|
||||
groupId = "org.http4k"
|
||||
artifactId = "http4k-server-apache"
|
||||
version = "3.260.0"
|
||||
category = "server"
|
||||
|
||||
[dependencies.javalin]
|
||||
groupId = "io.javalin"
|
||||
artifactId = "javalin"
|
||||
version = "3.10.1"
|
||||
category = "server"
|
||||
|
||||
[dependencies.pebble]
|
||||
groupId = "io.pebbletemplates"
|
||||
artifactId = "pebble"
|
||||
version = "3.1.4"
|
||||
default = true
|
||||
|
||||
[dependencies.logback]
|
||||
groupId = "ch.qos.logback"
|
||||
@@ -25,28 +66,85 @@ default = true
|
||||
groupId = "org.mariadb.jdbc"
|
||||
artifactId = "mariadb-java-client"
|
||||
version = "2.6.2"
|
||||
category = "database"
|
||||
|
||||
[dependencies.h2]
|
||||
groupId = "com.h2database"
|
||||
artifactId = "h2"
|
||||
version = "1.4.200"
|
||||
category = "database"
|
||||
|
||||
[dependencies.flyway]
|
||||
groupId = "org.flywaydb"
|
||||
artifactId = "flyway-core"
|
||||
version = "6.5.4"
|
||||
category = "database"
|
||||
|
||||
[dependencies.HikariCP]
|
||||
groupId = "com.zaxxer"
|
||||
artifactId = "HikariCP"
|
||||
version = "3.4.5"
|
||||
category = "database"
|
||||
|
||||
[dependencies.Ktorm]
|
||||
groupId = "me.liuwj.ktorm"
|
||||
artifactId = "ktorm-core"
|
||||
version = "3.0.0"
|
||||
category = "database"
|
||||
|
||||
[dependencies.Ktorm-Mysql]
|
||||
groupId = "me.liuwj.ktorm"
|
||||
artifactId = "ktorm-support-mysql"
|
||||
version = "3.0.0"
|
||||
version = "3.0.0"
|
||||
category = "database"
|
||||
|
||||
[dependencies.junit]
|
||||
groupId = "org.junit.jupiter"
|
||||
artifactId = "junit-jupiter"
|
||||
version = "5.6.2"
|
||||
scope = "test"
|
||||
category = "test"
|
||||
default = true
|
||||
|
||||
[dependencies.junit-params]
|
||||
groupId = "org.junit.jupiter"
|
||||
artifactId = "junit-jupiter-params"
|
||||
version = "5.6.2"
|
||||
scope = "test"
|
||||
category = "test"
|
||||
default = true
|
||||
|
||||
[dependencies.mokk]
|
||||
groupId = "io.mockk"
|
||||
artifactId = "mockk"
|
||||
version = "1.10.0"
|
||||
scope = "test"
|
||||
category = "test"
|
||||
|
||||
[dependencies.hamkrest]
|
||||
groupId = "com.natpryce"
|
||||
artifactId = "hamkrest"
|
||||
version = "1.7.0.3"
|
||||
scope = "test"
|
||||
category = "test"
|
||||
|
||||
[dependencies.assertJ]
|
||||
groupId = "org.assertj"
|
||||
artifactId = "assertj-core"
|
||||
version = "3.16.1"
|
||||
scope = "test"
|
||||
category = "test"
|
||||
default = true
|
||||
|
||||
[dependencies.Kodein-DI]
|
||||
groupId = "org.kodein.di"
|
||||
artifactId = "kodein-di-jvm"
|
||||
version = "7.0.0"
|
||||
category = "injection"
|
||||
|
||||
[dependencies.Koin]
|
||||
groupId = "org.koin"
|
||||
artifactId = "koin-core"
|
||||
version = "2.1.6"
|
||||
category = "injection"
|
||||
default = true
|
||||
@@ -46,9 +46,22 @@
|
||||
<artifactId>javalin</artifactId>
|
||||
<version>3.10.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-compress</artifactId>
|
||||
<version>1.20</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.koin</groupId>
|
||||
<artifactId>koin-core</artifactId>
|
||||
<version>2.1.6</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
|
||||
<testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>
|
||||
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "css",
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"css": "NODE_ENV=dev postcss build src/styles.pcss --output ../main/resources/assets/styles.css",
|
||||
"css-purge": "NODE_ENV=production postcss build src/styles.pcss --output ../main/resources/assets/styles.css"
|
||||
},
|
||||
"dependencies": {
|
||||
"autoprefixer": "^9.8.6",
|
||||
"cssnano": "^4.1.10",
|
||||
"postcss-cli": "^7.1.1",
|
||||
"postcss-import": "^12.0.1",
|
||||
"postcss-nested": "^4.2.3",
|
||||
"tailwindcss": "^1.5.1"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
module.exports = {
|
||||
plugins: [
|
||||
require('postcss-import'),
|
||||
require('postcss-nested'),
|
||||
require('tailwindcss'),
|
||||
require('autoprefixer'),
|
||||
require('cssnano')({
|
||||
preset: ['default', {
|
||||
discardComments: {
|
||||
removeAll: true,
|
||||
},
|
||||
}]
|
||||
}),
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
.btn {
|
||||
@apply font-semibold py-2 px-4 rounded;
|
||||
|
||||
&:focus {
|
||||
@apply outline-none shadow-outline;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
@apply font-extrabold;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-purple {
|
||||
@apply bg-purple-400 text-gray-800;
|
||||
|
||||
&:focus {
|
||||
@apply bg-purple-600;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
@apply bg-purple-600;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
.category{
|
||||
@apply text-lg inline-block text-center font-semibold text-gray-800 bg-green-300 rounded-full px-3 py-1 my-2;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
.input {
|
||||
@apply bg-gray-200 appearance-none border-2 border-gray-200 rounded w-full py-2 px-4 text-gray-700 leading-tight;
|
||||
|
||||
&:focus {
|
||||
@apply outline-none bg-white border-purple-500;
|
||||
}
|
||||
}
|
||||
|
||||
.input-label {
|
||||
@apply block text-gray-500 font-bold mb-1 pr-4;
|
||||
}
|
||||
|
||||
@screen md {
|
||||
.input-label {
|
||||
@apply text-right mb-0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/*noinspection CssUnknownTarget*/
|
||||
@import "tailwindcss/base";
|
||||
|
||||
/*noinspection CssUnknownTarget*/
|
||||
@import "tailwindcss/components";
|
||||
|
||||
@import "button.pcss";
|
||||
@import "category.pcss";
|
||||
@import "inputs.pcss";
|
||||
|
||||
/*noinspection CssUnknownTarget*/
|
||||
@import "tailwindcss/utilities";
|
||||
@@ -0,0 +1,17 @@
|
||||
module.exports = {
|
||||
purge: {
|
||||
content: [
|
||||
'../main/resources/views/**/*.twig'
|
||||
]
|
||||
},
|
||||
theme: {},
|
||||
variants: {
|
||||
textColor: ['responsive', 'hover', 'focus', 'group-hover'],
|
||||
},
|
||||
plugins: [
|
||||
],
|
||||
future: {
|
||||
removeDeprecatedGapUtilities: true,
|
||||
purgeLayersByDefault: true,
|
||||
},
|
||||
}
|
||||
+1885
File diff suppressed because it is too large
Load Diff
@@ -1,20 +0,0 @@
|
||||
package starter
|
||||
|
||||
import com.electronwill.nightconfig.core.Config as NightConfig
|
||||
import com.electronwill.nightconfig.core.file.FileConfig
|
||||
|
||||
data class StarterConfig(val dependencies: List<Dependency>)
|
||||
|
||||
class Config {
|
||||
fun load(): StarterConfig {
|
||||
val cfg = FileConfig.of("config.toml")
|
||||
cfg.load()
|
||||
val dependenciesNode: NightConfig = cfg["dependencies"]
|
||||
@Suppress("UNCHECKED_CAST") val valueMap = dependenciesNode.valueMap() as Map<String, NightConfig>
|
||||
val dependencies = valueMap.map { (name, values) ->
|
||||
Dependency(name, values.get("groupId"), values.get("artifactId"), values.get("version"), values.getOrElse("default", false))
|
||||
}
|
||||
return StarterConfig(dependencies)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
package starter
|
||||
|
||||
fun main() {
|
||||
val config = Config()
|
||||
val loaded = config.load()
|
||||
val server = Server(Views(PebbleModule().engine()),loaded)
|
||||
server.run()
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
package starter
|
||||
|
||||
data class Dependency(val name: String, val groupId: String, val artifactId: String, val version: String, val default: Boolean)
|
||||
data class Input(val name: String, val value: String? = null)
|
||||
@@ -1,30 +0,0 @@
|
||||
package starter
|
||||
|
||||
import io.javalin.Javalin
|
||||
|
||||
class Server(private val views: Views, private val conf: StarterConfig) {
|
||||
fun run() {
|
||||
val app = Javalin.create().start(7000)
|
||||
|
||||
app.get("/") { ctx ->
|
||||
val inputs = listOf(
|
||||
Input("name", "example"),
|
||||
Input("basePackage", "org.example")
|
||||
)
|
||||
ctx.result(views.index(conf.dependencies, inputs))
|
||||
ctx.contentType("text/html")
|
||||
}
|
||||
|
||||
app.post("/") { ctx ->
|
||||
val name = ctx.formParam("name")!!
|
||||
val basePackage = ctx.formParam("basePackage")!!
|
||||
|
||||
val deps = conf.dependencies.filter {
|
||||
ctx.formParam(it.name) != null
|
||||
}
|
||||
|
||||
ctx.result(views.pom(deps, name, basePackage))
|
||||
ctx.contentType("text/xml")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package starter
|
||||
|
||||
import com.mitchellbosecke.pebble.PebbleEngine
|
||||
import java.io.StringWriter
|
||||
|
||||
private 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()
|
||||
}
|
||||
|
||||
class Views(private val engine: PebbleEngine) {
|
||||
fun index(dependencies: List<Dependency>, inputs: List<Input>) = engine.render("views/index",
|
||||
mapOf("dependencies" to dependencies, "inputs" to inputs)
|
||||
)
|
||||
|
||||
fun pom(dependencies: List<Dependency>, name: String, basePackage: String) = engine.render("starter/pom",
|
||||
mapOf(
|
||||
"dependencies" to dependencies,
|
||||
"name" to name,
|
||||
"basePackage" to basePackage
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package starter
|
||||
|
||||
import com.electronwill.nightconfig.core.file.FileConfig
|
||||
import com.electronwill.nightconfig.core.Config as NightConfig
|
||||
|
||||
data class StarterConfig(val dependencies: List<Dependency>, val inputs: List<Input>)
|
||||
|
||||
class Config {
|
||||
fun load(): StarterConfig {
|
||||
val cfg = FileConfig.of("config.toml")
|
||||
cfg.load()
|
||||
val dependenciesNode: NightConfig = cfg["dependencies"]
|
||||
@Suppress("UNCHECKED_CAST") val dependenciesMap = dependenciesNode.valueMap() as Map<String, NightConfig>
|
||||
val dependencies = dependenciesMap.map { (name, values) ->
|
||||
Dependency(
|
||||
name,
|
||||
values["groupId"],
|
||||
values["artifactId"],
|
||||
values["version"],
|
||||
values.getOrElse("default", false),
|
||||
values.getEnumOrElse("category", Category.Other),
|
||||
values.getEnumOrElse("scope", Scope.Compile),
|
||||
)
|
||||
}
|
||||
|
||||
val inputsNode: NightConfig = cfg["inputs"]
|
||||
@Suppress("UNCHECKED_CAST") val inputMap = inputsNode.valueMap() as Map<String, NightConfig>
|
||||
val inputs = inputMap.map { (name, values) ->
|
||||
Input(name, values["display"], values["default"])
|
||||
}
|
||||
|
||||
return StarterConfig(dependencies, inputs)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package starter
|
||||
|
||||
import org.koin.core.context.startKoin
|
||||
import org.koin.dsl.bind
|
||||
import org.koin.dsl.module
|
||||
import starter.templates.MainTemplate
|
||||
import starter.templates.PomTemplate
|
||||
import starter.templates.Template
|
||||
|
||||
val mainModule = module {
|
||||
single { Config().load() }
|
||||
single { PebbleModule().engine() }
|
||||
single { Server(get(), get(), get()) }
|
||||
single { Views(get()) }
|
||||
single { ProjectZip(getAll()) }
|
||||
}
|
||||
|
||||
val templateModule = module {
|
||||
single { PomTemplate(get()) } bind Template::class
|
||||
single { MainTemplate(get()) } bind Template::class
|
||||
}
|
||||
|
||||
fun main() {
|
||||
val koin = startKoin {
|
||||
modules(mainModule, templateModule)
|
||||
}.koin
|
||||
val server = koin.get<Server>()
|
||||
server.run()
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package starter
|
||||
|
||||
enum class Category {
|
||||
Server, Injection, Database, Test, Other
|
||||
}
|
||||
|
||||
enum class Scope {
|
||||
Compile, Test
|
||||
}
|
||||
|
||||
data class Dependency(
|
||||
val name: String,
|
||||
val groupId: String,
|
||||
val artifactId: String,
|
||||
val version: String,
|
||||
val default: Boolean,
|
||||
val category: Category,
|
||||
val scope: Scope
|
||||
)
|
||||
|
||||
data class Input(val name: String, val display: String, val value: String? = null)
|
||||
|
||||
data class Project(
|
||||
val name: String,
|
||||
val basePackage: String,
|
||||
val inputs: List<Input>,
|
||||
val dependencies: List<Dependency>,
|
||||
)
|
||||
@@ -0,0 +1,23 @@
|
||||
package starter
|
||||
|
||||
import starter.templates.Template
|
||||
import starter.utils.ZipOutput
|
||||
import starter.utils.sanitizeFilename
|
||||
|
||||
class ProjectZip(private val templates: List<Template>) {
|
||||
|
||||
fun createZip(project: Project): String {
|
||||
val name: String
|
||||
|
||||
ZipOutput(sanitizeFilename(project.name)).use {
|
||||
name = it.name
|
||||
|
||||
templates.forEach { template ->
|
||||
it.write(template.path(project), template.render(project))
|
||||
}
|
||||
}
|
||||
|
||||
return name
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package starter
|
||||
|
||||
import io.javalin.Javalin
|
||||
import starter.utils.sanitizeFilename
|
||||
import java.io.File
|
||||
|
||||
class Server(
|
||||
private val views: Views,
|
||||
private val conf: StarterConfig,
|
||||
private val projectZip: ProjectZip,
|
||||
) {
|
||||
fun run() {
|
||||
val app = Javalin.create {
|
||||
it.addStaticFiles("/assets")
|
||||
}.start(7000)
|
||||
|
||||
app.get("/") { ctx ->
|
||||
ctx.result(views.index(conf.dependencies, conf.inputs))
|
||||
ctx.contentType("text/html")
|
||||
}
|
||||
|
||||
app.post("/") { ctx ->
|
||||
val deps = conf.dependencies.filter {
|
||||
ctx.formParam(it.name) != null
|
||||
}
|
||||
|
||||
val inputKeys = conf.inputs.map { it.name }
|
||||
val inputs = ctx.formParamMap()
|
||||
.filter { it.key in inputKeys }
|
||||
.map { (name, value) ->
|
||||
conf.inputs.find { it.name == name }!!.copy(value = value.first())
|
||||
}
|
||||
|
||||
val projectName = inputs.find { it.name == "name" }!!.value!!
|
||||
val basePackage = inputs.find { it.name == "basePackage" }!!.value!!
|
||||
val project = Project(projectName, basePackage, inputs, deps)
|
||||
|
||||
ctx.contentType("application/zip")
|
||||
ctx.header("Content-Disposition", "attachment; filename=\"${sanitizeFilename(projectName)}.zip\"")
|
||||
val zipFile = projectZip.createZip(project)
|
||||
ctx.result(File(zipFile).readBytes())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package starter
|
||||
|
||||
import com.mitchellbosecke.pebble.PebbleEngine
|
||||
import org.slf4j.LoggerFactory
|
||||
import starter.utils.render
|
||||
|
||||
class Views(private val engine: PebbleEngine) {
|
||||
private val logger = LoggerFactory.getLogger(javaClass)
|
||||
|
||||
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)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package starter.templates
|
||||
|
||||
import com.mitchellbosecke.pebble.PebbleEngine
|
||||
import starter.Project
|
||||
import starter.utils.render
|
||||
|
||||
class MainTemplate(private val engine: PebbleEngine) : Template {
|
||||
override fun path(project: Project) =
|
||||
project.basePackage.replace('.', '/') + "/" + project.name.toLowerCase().capitalize() + ".kt"
|
||||
|
||||
override fun render(project: Project) =
|
||||
engine.render("starter/main/main", mapOf("basePackage" to project.basePackage))
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package starter.templates
|
||||
|
||||
import com.mitchellbosecke.pebble.PebbleEngine
|
||||
import starter.Project
|
||||
import starter.utils.prettyPrintXml
|
||||
import starter.utils.render
|
||||
|
||||
class PomTemplate(private val engine: PebbleEngine) : Template {
|
||||
override fun path(project: Project) = "pom.xml"
|
||||
|
||||
override fun render(project: Project): String {
|
||||
val args: MutableMap<String, Any?> = mutableMapOf(
|
||||
"dependencies" to project.dependencies.sortedBy { it.scope },
|
||||
)
|
||||
|
||||
project.inputs.forEach {
|
||||
args[it.name] = it.value
|
||||
}
|
||||
|
||||
val rendered = engine.render("starter/pom/pom", args)
|
||||
return prettyPrintXml(rendered)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package starter.templates
|
||||
|
||||
import starter.Project
|
||||
|
||||
interface Template {
|
||||
fun path(project: Project): String
|
||||
fun render(project: Project): String
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package starter.utils
|
||||
|
||||
fun sanitizeFilename(inputName: String): String = inputName.replace("[^a-zA-Z0-9-_.]".toRegex(), "_")
|
||||
@@ -0,0 +1,11 @@
|
||||
package starter.utils
|
||||
|
||||
import com.mitchellbosecke.pebble.PebbleEngine
|
||||
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()
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package starter.utils
|
||||
|
||||
import org.w3c.dom.Document
|
||||
import org.w3c.dom.NodeList
|
||||
import org.xml.sax.InputSource
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.StringWriter
|
||||
import javax.xml.parsers.DocumentBuilderFactory
|
||||
import javax.xml.transform.OutputKeys
|
||||
import javax.xml.transform.TransformerFactory
|
||||
import javax.xml.transform.dom.DOMSource
|
||||
import javax.xml.transform.stream.StreamResult
|
||||
import javax.xml.xpath.XPathConstants
|
||||
import javax.xml.xpath.XPathFactory
|
||||
|
||||
|
||||
/*
|
||||
@see https://stackoverflow.com/a/33541820
|
||||
*/
|
||||
fun prettyPrintXml(xml: String, indent: Int = 4): String {
|
||||
// Turn xml string into a document
|
||||
val document: Document = DocumentBuilderFactory.newInstance()
|
||||
.newDocumentBuilder()
|
||||
.parse(InputSource(ByteArrayInputStream(xml.encodeToByteArray())))
|
||||
|
||||
// Remove whitespaces outside tags
|
||||
document.normalize()
|
||||
val xPath = XPathFactory.newInstance().newXPath()
|
||||
val nodeList = xPath.evaluate("//text()[normalize-space()='']",
|
||||
document,
|
||||
XPathConstants.NODESET) as NodeList
|
||||
for (i in 0 until nodeList.length) {
|
||||
val node = nodeList.item(i)
|
||||
node.parentNode.removeChild(node)
|
||||
}
|
||||
|
||||
// Setup pretty print options
|
||||
val transformerFactory = TransformerFactory.newInstance()
|
||||
transformerFactory.setAttribute("indent-number", indent)
|
||||
val transformer = transformerFactory.newTransformer()
|
||||
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8")
|
||||
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes")
|
||||
transformer.setOutputProperty(OutputKeys.INDENT, "yes")
|
||||
|
||||
// Return pretty print xml string
|
||||
val stringWriter = StringWriter()
|
||||
transformer.transform(DOMSource(document), StreamResult(stringWriter))
|
||||
return stringWriter.toString()
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package starter.utils
|
||||
|
||||
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry
|
||||
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream
|
||||
import java.io.File
|
||||
import java.nio.file.Paths
|
||||
|
||||
class ZipOutput(name: String) : AutoCloseable {
|
||||
private val baseDir = File(".").canonicalFile
|
||||
private val zipPath = Paths.get(baseDir.path, "$name.zip")
|
||||
private val zipFile = zipPath.toAbsolutePath().normalize().toFile().apply {
|
||||
createNewFile()
|
||||
}
|
||||
private val outputStream = ZipArchiveOutputStream(zipFile.outputStream())
|
||||
val name: String
|
||||
get() = zipFile.name
|
||||
|
||||
fun write(path: String, content: String) {
|
||||
val entry = ZipArchiveEntry(path)
|
||||
outputStream.putArchiveEntry(entry)
|
||||
outputStream.write(content.toByteArray())
|
||||
outputStream.closeArchiveEntry()
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
outputStream.finish()
|
||||
outputStream.close()
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 4.5 KiB |
File diff suppressed because one or more lines are too long
@@ -1,11 +0,0 @@
|
||||
<build>
|
||||
<plugins>
|
||||
|
||||
{% include "starter/plugins/@default" %}
|
||||
|
||||
{% include "starter/plugins/@kotlin" %}
|
||||
|
||||
{% include "starter/plugins/@shade" %}
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
@@ -0,0 +1,6 @@
|
||||
package {{ basePackage }}
|
||||
|
||||
|
||||
fun main() {
|
||||
println("Hello world!")
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
<project>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>{{ basePackage }}</groupId>
|
||||
<artifactId>{{ name | lower }}</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.target>14</maven.compiler.target>
|
||||
<maven.compiler.source>14</maven.compiler.source>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<main.class>{{ basePackage }}/{{ name | lower | capitalize }}Kt</main.class>
|
||||
</properties>
|
||||
|
||||
{% include "starter/@dependencies" %}
|
||||
|
||||
{% include "starter/@repositories" %}
|
||||
|
||||
{% include "starter/@plugins" %}
|
||||
|
||||
</project>
|
||||
+3
@@ -4,6 +4,9 @@
|
||||
<groupId>{{ dep.groupId }}</groupId>
|
||||
<artifactId>{{ dep.artifactId }}</artifactId>
|
||||
<version>{{ dep.version }}</version>
|
||||
{% if dep.scope == "Test" %}
|
||||
<scope>test</scope>
|
||||
{% endif %}
|
||||
</dependency>
|
||||
{% endfor %}
|
||||
</dependencies>
|
||||
@@ -0,0 +1,14 @@
|
||||
<build>
|
||||
<sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
|
||||
<testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>
|
||||
|
||||
<plugins>
|
||||
|
||||
{% include "starter/pom/plugins/@default" %}
|
||||
|
||||
{% include "starter/pom/plugins/@kotlin" %}
|
||||
|
||||
{% include "starter/pom/plugins/@shade" %}
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
+1
-1
@@ -19,6 +19,6 @@
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<jvmTarget>14</jvmTarget>
|
||||
<jvmTarget>${java.version}</jvmTarget>
|
||||
</configuration>
|
||||
</plugin>
|
||||
@@ -0,0 +1,23 @@
|
||||
<project>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>{{ basePackage }}</groupId>
|
||||
<artifactId>{{ name | lower }}</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<java.version>{{ javaVersion }}</java.version>
|
||||
<kotlin.version>{{ kotlinVersion }}</kotlin.version>
|
||||
<maven.compiler.target>${java.version}</maven.compiler.target>
|
||||
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<main.class>{{ basePackage }}/{{ name | lower | capitalize }}Kt</main.class>
|
||||
</properties>
|
||||
|
||||
{% include "starter/pom/@dependencies" %}
|
||||
|
||||
{% include "starter/pom/@repositories" %}
|
||||
|
||||
{% include "starter/pom/@plugins" %}
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,20 @@
|
||||
{% macro dependency(dependency) %}
|
||||
<label class="m-2">
|
||||
<input name="{{ dependency.name }}"
|
||||
type="checkbox"{% if dependency.default %} checked{% endif %}>
|
||||
<span>{{ dependency.name }}</span>
|
||||
</label>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro input(input) %}
|
||||
<div class="md:flex md:items-center mb-6">
|
||||
<div class="md:w-1/3">
|
||||
<label class="input-label" for="{{ input.name }}">
|
||||
{{ input.display }}
|
||||
</label>
|
||||
</div>
|
||||
<div class="md:w-2/3">
|
||||
<input name="{{ input.name }}" id="{{ input.name }}" class="input"{% if input.value %} value="{{ input.value }}"{% endif %}>
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
@@ -2,10 +2,14 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="/styles.css">
|
||||
<title>Kotlin Starter</title>
|
||||
</head>
|
||||
<body>
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
<main class="container mx-auto">
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,30 +1,26 @@
|
||||
{% extends "views/@base" %}
|
||||
|
||||
{% macro dependency(dependency) %}
|
||||
<label>
|
||||
<input name="{{ dependency.name }}" type="checkbox"{% if dependency.default %} checked{% endif %}>
|
||||
<span>{{ dependency.name }}</span>
|
||||
</label>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro input(input) %}
|
||||
<label>
|
||||
<span>{{ input.name }}</span>
|
||||
<input name="{{ input.name }}" type="text"{% if input.value %} value="{{ input.value }}"{% endif %}>
|
||||
</label>
|
||||
{% endmacro %}
|
||||
{% import "views/#macros" %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Kotlin Starter</h1>
|
||||
<form method="post">
|
||||
<h1 class="text-2xl font-bold text-purple-800 mb-4">Kotlin Starter</h1>
|
||||
<form method="post" class="w-full max-w-sm mx-auto">
|
||||
{% for input in inputs %}
|
||||
{{ input(input) }}
|
||||
{% endfor %}
|
||||
<br>
|
||||
{% for dependency in dependencies %}
|
||||
{{ dependency(dependency) }}
|
||||
{% endfor %}
|
||||
<br>
|
||||
<button type="submit">Submit</button>
|
||||
|
||||
<div class="mt-4">
|
||||
{% for category in dependencies %}
|
||||
<section>
|
||||
<h2 class="category">{{ category.key }}</h2>
|
||||
<ul>
|
||||
{% for dependency in category.value %}
|
||||
<li>{{ dependency(dependency) }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</section>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<button type="submit" class="w-full btn btn-purple">Submit</button>
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user