Kotlin DSL for HTML

Related tags

Kotlin kotlin html dsl
Overview

Official JetBrains Project GitHub license Kotlin npm TeamCity (simple build status)

kotlinx.html

A kotlinx.html library provides DSL to build HTML to Writer/Appendable or DOM at JVM and browser (or other JavaScript engine) for better Kotlin programming for Web.

Get started

See Getting started page for details how to include the library.

DOM

You can build DOM tree with JVM and JS naturally

See example for JavaScript-targeted Kotlin

window.setInterval({
    val myDiv = document.create.div("panel") {
        p { 
            +"Here is "
            a("https://kotlinlang.org") { +"official Kotlin site" }
        }
    }

    document.getElementById("container")!!.appendChild(myDiv)

    document.getElementById("container")!!.append {
        div {
            +"added it"
        }
    }
}, 1000L)

Stream

You can build HTML directly to Writer (JVM only) or Appendable (both JVM and JS)

System.out.appendHTML().html {
    body {
        div {
            a("https://kotlinlang.org") {
                target = ATarget.blank
                +"Main site"
            }
        }
    }
}

Documentation

See wiki pages

Building

See development page for details.

Comments
  • Stop relying on jcenter & bintray

    Stop relying on jcenter & bintray

    As of yesterday jcenter & bintray are sunsetting so most of the instructions here: https://github.com/kotlin/kotlinx.html/wiki/Getting-started will not work from 1st May 2021.

    It would be good to have org.jetbrains.kotlinx:kotlinx-html-jvm:0.7.2 in maven central.

    opened by Mahoney 21
  • Jcenter stopped providing the dependency

    Jcenter stopped providing the dependency

    Hi all,

    We started getting

     > Could not find org.jetbrains.kotlinx:kotlinx-html-jvm:0.7.1.
    

    a couple of hours ago and we had to update our configuration, adding a new maven repo:

    maven { url "https://dl.bintray.com/kotlin/kotlinx" }
    

    I would like to update the "Getting started" documentation, but I'm a bit afraid about modifying the wiki page 😂 However I hope this issue can help others ☮️

    opened by hamen 16
  • Base WASM Support and metadata publishing (1.4.0-rc)

    Base WASM Support and metadata publishing (1.4.0-rc)

    This is essentially a #154 but from feature branch for easier management until merged

    • Version bumped to 1.4.0-rc
    • BOTH js compiler mode enabled
    • WASM target added
    • gradle metadata publishing enabled
    • granular kotlin source sets enabled
    • TagConsumer and dsl abstraction level raised to allow for custom event object specifications
    • Native targets support

    @cy6erGn0m

    enhancement 
    opened by mpetuska 9
  • Cannot add a namespace to html tag

    Cannot add a namespace to html tag

    When I am trying to add a namespace to an html tag I have an exception "java.lang.IllegalArgumentException: Tag html has invalid attribute name xmlns"

    createHTML().html {
          attributes["xmlns"] = "http://www.w3.org/1999/xhtml"
          ...
    }
    

    According to w3c it is an absolutely valid scenario.

    Also it is impossible to set a namespace like this:

    createHTML().html {
          namespace = "http://www.w3.org/1999/xhtml"
          ...
    }
    

    because namespace is a val and cannot be reassigned.

    Exception happens in stream.kt after attribute validation (isValidXmlAttributeName() method call). As I see, any attribute which starts with "xml" prefix is considered invalid (is there a reason for this?).

    enhancement DSL 
    opened by isitinschi 7
  • WIP: Support for JSoup

    WIP: Support for JSoup

    Summary

    This PR aims to provide first-class support for the jsoup HTML parsing library, which is a mature and widely used project (particularly useful for scraping). Support for jsoup would greatly improve the versatility of this library and it's applicability across a wide range of potential use cases.

    Changes

    This PR would add a new type of tag consumer specific to the DOM structure used by jsoup, allowing for HTML to be appended to the aforementioned DOM using Kotlin's type-safe builder syntax and this library's preexisting tag & attribute definitions.

    Furthermore, many extension properties and methods have been added in order to better support Kotlin-style syntax when using jsoup functionality.

    Usage

    Changes have been encapsulated within a new artifact named kotlinx-html-jsoup.

    An example follows:

    val document = Document("")
    
    document.append {
        html {
            body {
                div {
                    +"This is a test."
                }
            }
        }
    }
    
    opened by apsoyka 7
  • FlowContent and PhrasingContent separation is useless

    FlowContent and PhrasingContent separation is useless

    Apparently those contents come from XSD, but in the end of the day, they are quite useless and very confusing in kotlinx.html.

    It does not help with static type check

    if I write something invalid according to XSD, like body > span > div

    body { // BODY creates FlowContent
        span { // SPAN creates PhrasingContent
    
            div { // DIV can only be created in _FlowContent_, not in SPAN
    
                // DIV is still allowed, because it is actually created in BODY, 
                // not in innermost parent SPAN
            }
        }
    }
    

    it is still silently accepted by the compiler and even leads to obscure IllegalStateException("You can't change tag attribute because it was already passed to the downstream") if I try to change attributes.

    To me this seems like a general problem of 'fall-through' builder design.

    It breaks the abstraction

    Both functions, FlowContent.i and PhrasingContent.i are identical: they produce the same I object. But there's no common abstraction between those two functions. Which leads to the third problem.

    It prevents reusable code

    I chose to use Tag as a basis for my DSL, which seemed like a good base class. But in the end I had to write the ugliest code in a decade of my career:

    fun Tag.mdl_icon(icon: String, text: String? = null) {
        if (this is FlowContent) {
    
            i("material-icons") {
                +icon
            }
            if (text != null) {
                span(classes = "visuallyhidden") {
                    +text
                }
            }
    
        } else if (this is PhrasingContent) {
    
            i("material-icons") {
                +icon
            }
            if (text != null) {
                span(classes = "visuallyhidden") {
                    +text
                }
            }
        }
    }
    

    Both if and else part are identical, but functions i and span are different. Condition like if (this is FlowContent || this is PhrasingContent) cannot work, of course.

    opened by kosiakk 7
  • Meta charset

    Meta charset

    Hello. Is there a way to declare <meta charset="UTF-8" />? Also, why meta function accepts code block, like a container-tag? Actual signature:

    meta(name: String?, content: String?, block: kotlinx.html.META.() -> kotlin.Unit)
    
    opened by Miha-x64 6
  • The onSubmitFunction for a form doesn't work.

    The onSubmitFunction for a form doesn't work.

    fun restoreListValues(e: Event) {
        println("I'm here")
    }
    
    fun doForm(trTag: TR) {
        trTag.td {
            form {
                name = "fmform"
                encType = FormEncType.textPlain
                action = "/server/"
                method = FormMethod.post
                onSubmitFunction = {
                    event - > restoreListValues(event)
                }
            }
        }
    }
    

    After executing, nothing happens to that form, I could use onSubmit, and the final form will have the onsubmit value, but the problem is that it expects a string, which means I could only refer to the final compiled javascript code which has no way to access the kotlinJS context.

    What I want is simple, just use a kotlinJS method to handle the onsubmit event of a form. How to achieve that?

    opened by Albert-Gao 6
  • Source code for kotlinx-html-jvm is missing in jCenter repo

    Source code for kotlinx-html-jvm is missing in jCenter repo

    The package kotlinx-html-jvm-0.6.1-sources.jar exists, but it contains only the jvm-specific sources like dom.kt and utilsImpl.ks.

    I guess, the main part should be in kotlinx-html-common, but this package is marked as optional in 2d518626e0b69a2c54edafc6a3bddfe4913a0885 and is actually missing in jCenter.

    deployment 
    opened by kosiakk 6
  • Error handling

    Error handling

    This is a proposal #21

    By default, onError will write to the underlying TagConsumer but there is a less-safe option to write to the innermost consumer using tag.consumer.

    opened by kosiakk 6
  • Enable building of jvm classes using the simple Kobalt syntax

    Enable building of jvm classes using the simple Kobalt syntax

    These few changes make it possible to compile and assemble (make jars) of kotlinx.html so that the jvm stuff can at least be built and used (maven build seems to be broken).

    If you'd like to use Kobalt, I can add the config for publishing jars to Sonatype, etc. It will also be simple.

    opened by pabl0rg 6
  • Wiki: 'Getting Started' page 404's

    Wiki: 'Getting Started' page 404's

    I visit https://github.com/Kotlin/kotlinx.html/wiki, and I see 'Getting Started' in the TOC

    image

    This links to https://github.com/Kotlin/kotlinx.html/Getting-started

    However, the URL 404's

    image
    opened by aSemy 0
  • JSDOMBuilder converts raw string contents to HTML tags

    JSDOMBuilder converts raw string contents to HTML tags

    I want to display a Map<String, String> in an HTML page.

    import kotlinx.browser.document
    import kotlinx.html.*
    import kotlinx.html.dom.*
    
    fun main() {
      document.body!!.append.div {
        pre {
          code {
            unsafe {
              raw("""
                val map: Map<String, String> = mapOf(
                  "key1" to "value1",
                  "key2" to "value2",
                )
              """.trimIndent())
            }
          }
        }
      }
    

    The code is not display 'raw' though, and the generic parameters are converted into HTML tags <string, string=""> - very strange!

    <div>
      <pre>
        <code>
          val map: Map<string, string=""> = mapOf(
            "key1" to "value1",
            "key2" to "value2",
          )
          </string,>
        </code>
      </pre>
    </div>
    

    The code rendered in my browser does not match the raw string.

    image

    Expected result

    If I don't use JSDOMBBuilder, then the HTML matches the raw content:

    import kotlinx.html.*
    import kotlinx.html.dom.createHTMLDocument
    import kotlinx.html.stream.createHTML
    
    fun main() {
      println(createHTML(prettyPrint = true).div {
        pre {
          code {
            unsafe {
              raw("""
                val map: Map<String, String> = mapOf(
                  "key1" to "value1",
                  "key2" to "value2",
                )
              """.trimIndent())
            }
          }
        }
      })
    }
    
    <div>
      <pre><code>val map: Map<String, String> = mapOf(
      "key1" to "value1",
      "key2" to "value2",
    )</code></pre>
    </div>
    

    Compose Web

    With Compose Web v1.2.2 I am also able to output raw content

    import org.jetbrains.compose.web.*
    import org.jetbrains.compose.web.css.*
    import org.jetbrains.compose.web.dom.*
    
    fun main() {
      renderComposable(rootElementId = "root") {
        Div {
          Pre {
            Code {
              Text(
                """
                  val map: Map<String, String> = mapOf(
                    "key1" to "value1",
                    "key2" to "value2",
                  )
                """.trimIndent()
              )
            }
          }
        }
      }
    }
    

    However, Compose Web escapes the angled brackets.

    <div><pre><code>
    val map: Map&lt;String, String&gt; = mapOf(
      "key1" to "value1",
      "key2" to "value2",
    )</code></pre></div>
    

    The result matches the raw input:

    image

    Versions

    • Kotlin/JS 1.7.20
    • Kotlinx HTML 0.7.5
    opened by aSemy 0
  • There is a vulnerability in jackson-databind:2.10.1,upgrade recommended

    There is a vulnerability in jackson-databind:2.10.1,upgrade recommended

    https://github.com/Kotlin/kotlinx.html/blob/3466e6f40ce242e4dfacdadd65571abd2385bb58/build.gradle.kts#L204

    CVE-2020-25649 CVE-2022-42004 CVE-2022-42003 CVE-2020-36518

    Recommended upgrade version:2.12.7.1

    opened by QiAnXinCodeSafe 0
  • README needs a

    README needs a "slows down compilation considerably" warning

    We've migrated a significant number of HTML+Groovy templates over the Kotlinx.html.

    The DSL in fantastic! We're super happy developers using it... until we compile.

    As mentioned in this issue the DSL compiles very, VERY, slow. We have no way of knowing exactly how much time is spend by the compiler on each file (if anyone knows please let me know), but every time we ported a bunch of templates to Kotlinx.html, we saw a stark increase in compile times.

    If I would have know this up front, I'd have chosen a different solution. And hence I believe this project's README should warn (potential) users for this caveat.

    opened by cies 0
  • Add htmlFor parameter to label element

    Add htmlFor parameter to label element

    Currently, you have to do:

    checkBoxInput(classes = "form-check-input", name = "myName") {
        id = "myId"
        value = "myValue"
    }
    
    label(classes="myclass") {
      htmlFor="myId"
      +"Check me" 
    }
    

    However, a label without for attribute is not very common. It should be a parameter, so that it is much more concise to write:

    label(classes = "myclass",  htmlFor = "myId") {
      +"Check me" 
    }
    
    opened by JohannesOehm 0
  • Attribute value is not yet defined for tag input

    Attribute value is not yet defined for tag input

    Got the following error trying to get the value of an input:

    message: "Attribute value is not yet defined for tag input"
    

    Code:

    import kotlinx.browser.document
    import kotlinx.html.div
    import kotlinx.html.dom.append
    import kotlinx.html.h2
    import kotlinx.html.id
    import kotlinx.html.input
    import kotlinx.html.js.onKeyUpFunction
    import kotlinx.html.style
    import kotlinx.html.unsafe
    import org.w3c.dom.HTMLElement
    
    object HtmlIds {
        const val base58Result = "base58-result"
    }
    
    /**
     * Test application for the base58 library.
     *
     * It helps test that the code works on a browser.
     */
    fun main() {
        byId("root").append {
            h2 {
                +"Enter some text:"
            }
            input {
                placeholder = "Text to encode to base58"
                onKeyUpFunction = { _ ->
                    byId(HtmlIds.base58Result).textContent = value
                }
            }
            div {
                id = HtmlIds.base58Result
                style {
                    unsafe { raw("padding: 10px; background: green; color: white") }
                }
            }
        }
    }
    
    private fun byId(id: String): HTMLElement {
        return (document.getElementById(id) as HTMLElement?)!!
    }
    
    
    opened by renatoathaydes 0
Releases(0.8.0)
Owner
Kotlin
Kotlin Tools and Libraries
Kotlin
A CLI tool to convert multi-module Jetpack Compose compiler metrics into beautiful HTML reports

A CLI tool to convert multi-module Jetpack Compose compiler metrics into beautiful HTML reports 1. What are Jetpack Compose compiler metrics? The Comp

Jaya Surya Thotapalli 116 Jan 3, 2023
Android + Kotlin + Github Actions + ktlint + Detekt + Gradle Kotlin DSL + buildSrc = ❤️

kotlin-android-template ?? A simple Github template that lets you create an Android/Kotlin project and be up and running in a few seconds. This templa

Nicola Corti 1.5k Jan 3, 2023
A Kotlin DSL wrapper around the mikepenz/MaterialDrawer library.

MaterialDrawerKt Create navigation drawers in your Activities and Fragments without having to write any XML, in pure Kotlin code, with access to all t

Márton Braun 517 Nov 19, 2022
{ } Declarative Kotlin DSL for choreographing Android transitions

Transition X Kotlin DSL for choreographing Android Transitions TransitionManager makes it easy to animate simple changes to layout without needing to

Arunkumar 520 Dec 16, 2022
Kotlin Dsl for Android RecyclerView

KRecyclerDsl Kotlin Dsl for Android RecyclerView Exemple Sample project recyclerView.adapter = dataClassAdapter<MyView, MyDataClass>(R.layout.my_view,

Thomas Girard 14 Mar 31, 2019
The most complete and powerful data-binding library and persistence infra for Kotlin 1.3, Android & Splitties Views DSL, JavaFX & TornadoFX, JSON, JDBC & SQLite, SharedPreferences.

Lychee (ex. reactive-properties) Lychee is a library to rule all the data. ToC Approach to declaring data Properties Other data-binding libraries Prop

Mike 112 Dec 9, 2022
Nice and simple DSL for Espresso in Kotlin

Kakao Nice and simple DSL for Espresso in Kotlin Introduction At Agoda, we have more than 1000 automated tests to ensure our application's quality and

Agoda Company Pte Ltd. 1.1k Nov 22, 2022
DSL for constructing the drawables in Kotlin instead of in XML

Android Drawable Kotlin DSL DSL for constructing the drawables in Kotlin instead of in XML Examples Shape drawables <?xml version="1.0" encoding="utf-

Infotech Group 178 Dec 4, 2022
Lightweight Kotlin DSL dependency injection library

Warehouse DSL Warehouse is a lightweight Kotlin DSL dependency injection library this library has an extremely faster learning curve and more human fr

Osama Raddad 18 Jul 17, 2022
Code generation of Kotlin DSL for AWS CDK

Code generation of Kotlin DSL for AWS CDK

Semantic Configuration 5 Dec 24, 2022
Regular expression DSL on Kotlin

Examples Characters Construct Equivalent Matches x character(Char) The character x \\ character('\\') The backslash character \0n octal(OctalValue(7))

null 1 Oct 7, 2021
Kotlin Object Notation - Lightweight DSL to build fluid JSON trees

Kotlin Object Notation Lightweight kotlin MPP DSL for building JSON trees Setup Just drop the dependency in your commonMain sourceSet kotlin { sourc

Martynas Petuška 43 Dec 10, 2022
Kotlin parser library with an easy-to-use DSL

Pratt Library for parsing expressions and a beautiful Kotlin DSL Just define your operators and operands with the Kotlin DSL and the parser is ready!

furetur 9 Oct 17, 2022
Kotlin DSL for Junit5

Kupiter is Kotlin DSL for Junit5. Current API is only for dynamic tests. Get it repositories { maven { url 'https://jitpack.io' } } dependencies

Andrius Semionovas 14 Oct 3, 2022
Kotlin-dsl-sample - Preferences project on android

kotlin-dsl-example Sample preferences project on android. How to use val

null 1 Dec 30, 2021
GitHub Actions Kotlin DSL

GitHub Actions Kotlin DSL Work in progress! The goal is to be able to describe GH Actions in Kotlin with all its perks, like: workflow( name = "Te

Piotr Krzemiński 271 Dec 26, 2022
A simple, classic Kotlin MVI implementation based on coroutines with Android support, clean DSL and easy to understand logic

A simple, classic Kotlin MVI implementation based on coroutines with Android support, clean DSL and easy to understand logic

Nek.12 4 Oct 31, 2022
Kotlin DSL inspired by bhailang.js

Kotlin DSL inspired by bhailang.js

kaiwalya 1 Mar 22, 2022
A light weight Compose Animation library to choreograph low level Animation API through Kotlin DSL.

Koreography Choreograph your Compose Animation ?? ?? A lightweight Compose Animation utility library to choreograph low-level Animation API (https://d

Sagar Viradiya 107 Jan 8, 2023