@@ -3,14 +3,189 @@ package com.github.wakingrufus.funk.htmx
33import com.github.wakingrufus.funk.core.SpringDsl
44import com.github.wakingrufus.funk.core.SpringDslContainer
55import com.github.wakingrufus.funk.core.SpringDslMarker
6+ import com.github.wakingrufus.funk.htmx.route.HxRoute
7+ import com.github.wakingrufus.funk.htmx.route.noParam
8+ import com.github.wakingrufus.funk.htmx.route.withAuth
9+ import com.github.wakingrufus.funk.htmx.route.withParam
10+ import com.github.wakingrufus.funk.htmx.route.withParamAndAuth
11+ import com.github.wakingrufus.funk.htmx.template.HtmxTemplate
12+ import kotlinx.html.BODY
13+ import kotlinx.html.TagConsumer
14+ import kotlinx.html.body
15+ import kotlinx.html.dom.createHTMLDocument
16+ import kotlinx.html.dom.serialize
17+ import kotlinx.html.head
18+ import kotlinx.html.html
19+ import kotlinx.html.script
20+ import org.springframework.beans.factory.BeanFactory
21+ import org.springframework.http.MediaType
22+ import org.springframework.web.servlet.function.RouterFunctionDsl
23+ import org.springframework.web.servlet.function.ServerResponse
24+ import java.security.Principal
625
726@SpringDslMarker
827class HtmxDsl : SpringDsl {
928 val pages = ArrayList <HtmxPage >()
29+ internal var routes: MutableList <HxRoute > = mutableListOf ()
1030
1131 @SpringDslMarker
12- fun page (path : String , config : HtmxPage .() -> Unit ) {
13- pages.add(HtmxPage (path).apply (config))
32+ fun page (path : String , template : BODY .() -> Unit = {}) {
33+ pages.add(HtmxPage (path).apply { initialLoad(template) })
34+ }
35+
36+
37+ fun addRoute (route : HxRoute ) {
38+ routes.add(route)
39+ }
40+
41+ /* *
42+ * use when declaring a GET route that takes no parameters
43+ */
44+ @SpringDslMarker
45+ inline fun <reified CONTROLLER : Any , RESP : Any > get (
46+ path : String ,
47+ noinline binding : CONTROLLER .() -> RESP ,
48+ renderer : HtmxTemplate <RESP >
49+ ): HxRoute {
50+ return noParam(
51+ RouterFunctionDsl ::GET ,
52+ path = path,
53+ controllerClass = CONTROLLER ::class .java,
54+ binding = binding,
55+ renderer = renderer
56+ )
57+ .also { addRoute(it) }
58+ }
59+
60+ @SpringDslMarker
61+ inline fun <reified CONTROLLER : Any , RESP : Any > get (
62+ path : String ,
63+ noinline binding : CONTROLLER .() -> RESP ,
64+ crossinline renderer : TagConsumer <* >.(RESP ) -> Unit
65+ ): HxRoute {
66+ return get(path, binding) { appendable, input -> renderer.invoke(appendable, input) }
67+ }
68+
69+ /* *
70+ * use when declaring a GET route that takes no parameters, but uses security
71+ */
72+ @SpringDslMarker
73+ inline fun <reified CONTROLLER : Any , USER : Principal , RESP : Any > get (
74+ path : String ,
75+ noinline binding : CONTROLLER .(USER ? ) -> RESP ,
76+ renderer : HtmxTemplate <RESP >
77+ ): HxRoute {
78+ return withAuth(
79+ RouterFunctionDsl ::GET ,
80+ path = path,
81+ controllerClass = CONTROLLER ::class .java,
82+ binding = binding,
83+ renderer = renderer
84+ )
85+ .also { addRoute(it) }
86+ }
87+
88+ @SpringDslMarker
89+ inline fun <reified CONTROLLER : Any , USER : Principal , RESP : Any > get (
90+ path : String ,
91+ noinline binding : CONTROLLER .(USER ? ) -> RESP ,
92+ crossinline renderer : TagConsumer <* >.(RESP ) -> Unit
93+ ): HxRoute {
94+ return get(path, binding) { appendable, input -> renderer.invoke(appendable, input) }
95+ }
96+
97+ @SpringDslMarker
98+ inline fun <reified CONTROLLER : Any , reified REQ : Record , RESP : Any > route (
99+ verb : HttpVerb ,
100+ path : String ,
101+ noinline binding : CONTROLLER .(REQ ) -> RESP ,
102+ crossinline renderer : TagConsumer <* >.(RESP ) -> Unit
103+ ): HxRoute {
104+ return route(verb, path, binding) { appendable, input -> renderer.invoke(appendable, input) }
105+ }
106+
107+ @SpringDslMarker
108+ inline fun <reified CONTROLLER : Any , reified REQ : Record , RESP : Any > route (
109+ verb : HttpVerb ,
110+ path : String ,
111+ noinline binding : CONTROLLER .(REQ ) -> RESP ,
112+ renderer : HtmxTemplate <RESP >
113+ ): HxRoute {
114+ return withParam(
115+ routerFunction = when (verb) {
116+ HttpVerb .GET -> RouterFunctionDsl ::GET
117+ HttpVerb .POST -> RouterFunctionDsl ::POST
118+ HttpVerb .PUT -> RouterFunctionDsl ::PUT
119+ HttpVerb .PATCH -> RouterFunctionDsl ::PATCH
120+ HttpVerb .DELETE -> RouterFunctionDsl ::DELETE
121+ },
122+ path = path,
123+ requestClass = REQ ::class .java,
124+ controllerClass = CONTROLLER ::class .java,
125+ binding = binding,
126+ renderer = renderer
127+ )
128+ .also { addRoute(it) }
129+ }
130+
131+ @SpringDslMarker
132+ inline fun <reified CONTROLLER : Any , reified REQ : Record , USER : Principal , RESP : Any > route (
133+ verb : HttpVerb ,
134+ path : String ,
135+ noinline binding : CONTROLLER .(USER ? , REQ ) -> RESP ,
136+ crossinline renderer : TagConsumer <* >.(RESP ) -> Unit
137+ ): HxRoute {
138+ return route(verb, path, binding) { appendable, input -> renderer.invoke(appendable, input) }
139+ }
140+
141+ @SpringDslMarker
142+ inline fun <reified CONTROLLER : Any , reified REQ : Record , USER : Principal , RESP : Any > route (
143+ verb : HttpVerb ,
144+ path : String ,
145+ noinline binding : CONTROLLER .(USER ? , REQ ) -> RESP ,
146+ renderer : HtmxTemplate <RESP >
147+ ): HxRoute {
148+ return withParamAndAuth(
149+ routerFunction = when (verb) {
150+ HttpVerb .GET -> RouterFunctionDsl ::GET
151+ HttpVerb .POST -> RouterFunctionDsl ::POST
152+ HttpVerb .PUT -> RouterFunctionDsl ::PUT
153+ HttpVerb .PATCH -> RouterFunctionDsl ::PATCH
154+ HttpVerb .DELETE -> RouterFunctionDsl ::DELETE
155+ },
156+ path = path,
157+ requestClass = REQ ::class .java,
158+ controllerClass = CONTROLLER ::class .java,
159+ binding = binding,
160+ renderer = renderer
161+ )
162+ .also { addRoute(it) }
163+ }
164+
165+ fun registerRoutes (beanFactory : BeanFactory , dsl : RouterFunctionDsl ) {
166+ dsl.apply {
167+ pages.forEach {
168+ GET (it.path) { request ->
169+ ServerResponse .ok()
170+ .contentType(MediaType .TEXT_HTML )
171+ .body(
172+ createHTMLDocument().html {
173+ head {
174+ script {
175+ src = " https://unpkg.com/htmx.org@2.0.4"
176+ }
177+ }
178+ body {
179+ it.initialLoad.invoke(this )
180+ }
181+ }.serialize(false )
182+ )
183+ }
184+ }
185+ routes.forEach { route ->
186+ route.registerRoutes(beanFactory, this )
187+ }
188+ }
14189 }
15190}
16191
0 commit comments