Kotlin/kotlinx.html

Please make the streaming consumer easier to work with

reubenfirmin opened this issue · 2 comments

When creating custom components, it's very easy to get attributes and tag properties in the wrong order, which leads you to run into:

java.lang.IllegalStateException: You can't change tag attribute because it was already passed to the downstream
	at kotlinx.html.consumers.DelayedConsumer.onTagAttributeChange(delayed-consumer.kt:16)

This can be avoided by reordering code, but it's ultimately an implementation detail of the library. Please provide either an update to the streaming consumer so that it isn't sensitive to attribute vs content order, or provide an alternate consumer allowing creation of html fragments which is non-streaming.

As another example (and I think indicative of this being a design problem), the DSL has:

@HtmlTagMarker
inline fun <T, C : TagConsumer<T>> C.div(classes : String? = null, crossinline block : DIV.() -> Unit = {}) : T = DIV(attributesMapOf("class", classes), this).visitAndFinalize(this, block)

and

@HtmlTagMarker
inline fun FlowContent.div(classes : String? = null, crossinline block : DIV.() -> Unit = {}) : Unit = DIV(attributesMapOf("class", classes), consumer).visit(block)

The latter can be used almost anywhere. The only place that I know the former can be used is strung from the appendHTML() function. The problem with this is that replacing an element (e.g. via htmx) can sometimes result in awkward workarounds to avoid the hierarchy changing, because most custom components are written only with FlowContent in mind.