Repository: tipsy/javalin
Pull request #571 (2019-05-01 18:21:50)

[plugins] Add vue plugin


Patch:
diff --git a/src/main/java/io/javalin/plugin/rendering/vue/JavalinVue.kt b/src/main/java/io/javalin/plugin/rendering/vue/JavalinVue.kt
new file mode 100644
index 00000000..5ecf4379
--- /dev/null
+++ b/src/main/java/io/javalin/plugin/rendering/vue/JavalinVue.kt
@@ -0,0 +1,36 @@
+/*
+ * Javalin - https://javalin.io
+ * Copyright 2017 David Åse
+ * Licensed under Apache 2.0: https://github.com/tipsy/javalin/blob/master/LICENSE
+ */
+
+package io.javalin.plugin.rendering.vue
+
+import io.javalin.http.Context
+import io.javalin.http.Handler
+import io.javalin.http.util.ContextUtil
+import io.javalin.plugin.json.JavalinJson
+import java.io.File
+
+object JavalinVue {
+
+    private val cachedTemplate: String by lazy { createLayout(localhost = false) }
+
+    fun render(component: String) = Handler { ctx ->
+        val view = if (ContextUtil.isLocalhost(ctx)) createLayout(localhost = true) else cachedTemplate
+        ctx.html(view.replace("@routeParams", getParams(ctx)).replace("@routeComponent", component)) // insert current route component
+    }
+
+    fun createLayout(localhost: Boolean): String {
+        val vueFolder = if (localhost) "src/main/resources/vue" else this.javaClass.classLoader.getResource("vue").path
+        val headContent = File(vueFolder).walkTopDown().filter { it.extension == "vue" }.joinToString("") { it.readText() } // // find and concat .vue files
+        return File("$vueFolder/layout.html").readText().replace("@componentRegistration", "@routeParams$headContent") // inject variable for route-params
+    }
+
+    fun getParams(ctx: Context) = """<script>
+          Vue.prototype.${"$"}javalin = {
+          pathParams: ${JavalinJson.toJson(ctx.pathParamMap())},
+          queryParams: ${JavalinJson.toJson(ctx.queryParamMap())}
+      }</script>"""
+
+}


Test patch:
diff --git a/src/test/java/io/javalin/TestJavalinVue.kt b/src/test/java/io/javalin/TestJavalinVue.kt
new file mode 100644
index 00000000..27899d3b
--- /dev/null
+++ b/src/test/java/io/javalin/TestJavalinVue.kt
@@ -0,0 +1,31 @@
+/*
+ * Javalin - https://javalin.io
+ * Copyright 2017 David Åse
+ * Licensed under Apache 2.0: https://github.com/tipsy/javalin/blob/master/LICENSE
+ */
+
+package io.javalin
+
+import io.javalin.plugin.rendering.vue.JavalinVue
+import org.assertj.core.api.Assertions.assertThat
+import org.junit.Test
+
+class TestJavalinVue {
+
+    @Test
+    fun `hello vue world`() = TestUtil.test { app, http ->
+        app.get("/vue/:my-param") {
+            it.html(JavalinVue.createLayout(localhost = false) // need to use classpath for test
+                    .replace("@routeParams", JavalinVue.getParams(it))
+                    .replace("@routeComponent", "<test-component></test-component>")
+            )
+        }
+        val response = http.getBody("/vue/test-path-param?qp=test-query-param")
+        assertThat(response).contains("""pathParams: {"my-param":"test-path-param"}""")
+        assertThat(response).contains("""queryParams: {"qp":["test-query-param"]}""")
+        assertThat(response).contains("""Vue.component("test-component", {template: "#test-component"});""")
+        assertThat(response).contains("<body><test-component></test-component></body>")
+    }
+
+}
+
diff --git a/src/test/resources/vue/layout.html b/src/test/resources/vue/layout.html
new file mode 100644
index 00000000..69ade1c6
--- /dev/null
+++ b/src/test/resources/vue/layout.html
@@ -0,0 +1,2 @@
+<head>@componentRegistration</head>
+<body>@routeComponent</body>
diff --git a/src/test/resources/vue/test-component.vue b/src/test/resources/vue/test-component.vue
new file mode 100644
index 00000000..1ad9423b
--- /dev/null
+++ b/src/test/resources/vue/test-component.vue
@@ -0,0 +1,6 @@
+<template id="test-component">
+    <div>Test</div>
+</template>
+<script>
+    Vue.component("test-component", {template: "#test-component"});
+</script>