Git Product home page Git Product logo

kotlinx.html's Introduction

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

kotlinx.html

The kotlinx.html library provides a DSL to build HTML to Writer/Appendable or DOM. Available to all Kotlin Multiplatform targets and browsers (or other WasmJS or JavaScript engines) for better Kotlin programming for Web.

Get started

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

DOM

You can build a DOM tree with JVM, JS, and WASM. The following example shows how to build the DOM for WasmJs-targeted Kotlin:

import kotlinx.browser.document
import kotlinx.browser.window
import kotlinx.html.a
import kotlinx.html.div
import kotlinx.html.dom.append
import kotlinx.html.dom.create
import kotlinx.html.p

fun main() {
    val body = document.body ?: error("No body")
    body.append {
        div {
            p {
                +"Here is "
                a("https://kotlinlang.org") { +"official Kotlin site" }
            }
        }
    }

    val timeP = document.create.p {
        +"Time: 0"
    }

    body.append(timeP)

    var time = 0
    window.setInterval({
        time++
        timeP.textContent = "Time: $time"

        return@setInterval null
    }, 1000)
}

Stream

You can build HTML directly to Writer (JVM) or Appendable (Multiplatform)

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.

kotlinx.html's People

Contributors

anton-bannykh avatar atomcat1978 avatar cy6ergn0m avatar dmitrievanthony avatar e5l avatar elizarov avatar etolstoy avatar guenhter avatar gzoritchak avatar hfhbd avatar hhariri avatar ilgonmic avatar ilyagulya avatar jonare avatar jonnyzzz avatar kosiakk avatar kotlinisland avatar lorenzsimon avatar marcinaman avatar orangy avatar ptalanov avatar reisi007 avatar romanart avatar severn-everett avatar simonmarquis avatar soywiz avatar sschuberth avatar syrou avatar vitek999 avatar vonox7 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

kotlinx.html's Issues

Function th is not working:

Function th is not working, it generates ClassCastException, version 0.6.4.

import kotlinx.html.js.*
import kotlinx.html.dom.create
import kotlin.browser.document

fun main(args: Array<String>) {
    val td = document.create.td()
    val th = document.create.th()
    println("OK")
}

Style content gets escaped

style(content = "ul > li { ... }")

will be rendered like

<style>
ul &gt; li { ... }
</style>

which is wrong. Using

style {
    unsafe { +" ... "}
}

as a workaround at the moment.

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.

missing tag figcaption

The figcaption tag is missing in the kotlinx DSL.

See http://w3c.github.io/html-reference/figcaption.html

In fact it would be even more helpful if the docs could detail out how to add a custom tag on top of the existing library (if this is possible with kotlinx) (ie to show how to extend the kotlinx DSL). In https://github.com/kotlin/kotlinx.html/wiki/Micro-templating-and-DSL-customizing you already do so to some extent, but custom tags don't seem not to be covered there.

For now the only workaround seems to be

StringBuilder().apply {
    appendHTML().figure() {
        img {
            src = movie.movieInfo?.coverImageURL
        }
    }
    append("<figcaption class='picture-item__title pull-left'>" + movie.name + """</figcaption>""")
}

but by using kotlinx I'd like to avoid simple unstructured string-building.

Could not find org.jetbrains.kotlinx:kotlinx-html:0.6.4

I'm trying to test the HTML Application, my gradle.build dependencies are:

dependencies {
    compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
    compile "org.jetbrains.ktor:ktor-core:$ktor_version"
    compile 'org.jetbrains.kotlinx:kotlinx-html:0.6.4'
    compile "org.jetbrains.ktor:ktor-netty:$ktor_version"
    compile "org.apache.commons:commons-email:1.4"
    compile "org.slf4j:slf4j-simple:1.7.25"
    compile "ch.qos.logback:logback-classic:1.2.1"
    testCompile group: 'junit', name: 'junit', version: '4.12'
}

I got the below error while running gradle build:

Could not find org.jetbrains.kotlinx:kotlinx-html:0.6.4

Error handling

In case of exception, current implementation simply aborts the processing.

I've introduced an onError handler in the TagConsumer, so that the library:

  1. Handles errors in a general manner
  2. Always properly closes all the tags
  3. If error handler does not re-trow the exception, the rendering continues

As the result, it's possible to use such TagConsumer:

class SafeHtmlOutput(val result: PrintWriter) : TagConsumer<PrintWriter> by result.appendHTML()

    override fun onError(exception: Exception) {
        // prints a very basic error block
        h4(classes = "error") {
            style = "background-color: red; text-color: white"
            onTagContent(exception.message ?: "Unknown error")
        }

        exception.printStackTrace() // send to stderr log
    }

}

It cannot get much simpler than that. As you see, it has all the freedom to properly react to the exception. For example, the tag contents might simply remain empty, while the rest of the page remains fully-functional.

I use Kotlinx.html for stream-like processing: page headers are sent almost instantly (by abusing TagConsumer.finalize and PrintWriter.flush), while the rest is generated gradually, like in the original PHP (but with good compiler) for lighting-fast zero-delay instant content delivery. Therefore errors are rather common and must be handled.

Attribute Extensions don't work.

I was trying to add additional attribute properties to make some of them easier, but setting attributes as extension properties never prints out to the final html.

For example, adding a data-toggle attribute to a button:

var BUTTON.dataToggle: String?
    get() = attributes["data-toggle"]
    set(value) {
        attributes["data-toggle"]
    }

Calling this, doesn't work:

button {
    classes = setOf("navbar-toggler", "d-lg-none")
    type = ButtonType.button
    dataToggle = "dropdown"
}

But this does:

button {
    classes = setOf("navbar-toggler", "d-lg-none")
    type = ButtonType.button
    attributes["data-toggle"] = "dropdown"}

Is there something weird going on that I can't see?

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?

Kotlin: Unresolved reference

Trying to use these html tags in a kotlin2js project with gradle:

apply plugin: 'kotlin2js'

repositories {
    mavenCentral()
    jcenter()
}

dependencies {
    compile "org.jetbrains.kotlin:kotlin-stdlib-js:$kotlin_version"

    def kotlinx_html_version = "0.6.3"
    compile "org.jetbrains.kotlinx:kotlinx-html-jvm:${kotlinx_html_version}"

    compile "org.jetbrains.kotlinx:kotlinx-html-js:${kotlinx_html_version}"
}

but import kotlinx.html.* in my Main.kt file never works. Always get Unresolved reference for any tags. I feel like I'm very close. Sorry, new to kotlin and kotlinjs.

I followed steps in https://medium.com/@ali.muzaffar/building-a-full-stack-web-app-in-kotlin-af8e8fe1f5dc and got everything working. Now just trying to add this kotlinx html support.

Gradle code on getting started page is out of date

Using Gradle 3.0, Kotlin 1.0.3, and the following build.gradle file, I get a compilation error:

Could not find method compileClient() for arguments [org.jetbrains.kotlinx:kotlinx.html.js:0.5.10] on object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler.

I get a different error if using "${kotlinx.html.version}" in place of the version number:

Could not get unknown property 'kotlinx' for object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler.

What I did get to work properly was calling the compile method on the js version of the library, but I doubt that the behavior is intended.

buildscript {
    ext.kotlin_version = '1.0.3'
    repositories {
       mavenCentral()
    }
    dependencies {
       classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

apply plugin: 'kotlin'

repositories {
    maven {
        url "http://dl.bintray.com/kotlinx/kotlinx"
    }
}

dependencies {
    compile "org.jetbrains.kotlinx:kotlinx.html.jvm:0.5.10"
    compileClient "org.jetbrains.kotlinx:kotlinx.html.js:0.5.10"
}

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)

Escaping of single quote in event handlers

The single quotes are not escaped in event handlers. For instance, if I have an event like oninput="myFunction('id')", the generated html replaces ' with &apos; which is not expected.

link tag should have "type" attribute as a parameter

There are many links like this:

link("/myapp.ico", "shortcut icon", "image/x-icon")

where image/x-icon is type attribute. Using it via attributes["type"] = "image/png" is not convenient for such one-liners.

Invalid html generated with pretty-print

        val x = StringBuilder().appendHTML().html {
            body {
                article {
                    p {
                    }
                    a {
                        +"aaa"
                    }
                    span { }
                }
            }
        }.toString()

Indent is placed in the wrong place, appending space to content.

Unsafe content support

it should be way to build unsafe content (with no escaping) as well

Like this

script {
    +"some script text"
}

Missing License File

Couldn't see a license file for the kotlinx.html repository. Which license is used for KotlinX HTML?

tag input type checkbox don't work

I have this code below, but it don't work:

      classes = setOf("form-group")
      label {
        for_ = "exampleInputFile"
        text("File input")
      }
      input {
        type = enumValueOf("file")
        id = "exampleInputFile"
      }
      p {
        classes = setOf("help-block")
        text("Example block-level help text here.")
      }
    }
    div {
      classes = setOf("checkbox")
      label {
        input {
          type = enumValueOf("checkbox")
          text("Check me out")
        }
      }
    }```
When I run this code in my browser, it show the error:
```uncaught exception: IllegalStateException: No enum constant kotlinx.html.InputType.checkbox```

How can I fix that?

Add HTML attribute lang

I would add it myself and make a pull request but for a reason beyond me the code excludes any attributes called lang. Why is that ?

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 2d51862 and is actually missing in jCenter.

Composition without passing parent

I would like to compose methods without passing the parent. Need some kind of add method. Something like below:

private fun renderGame(g: Game) = document.create.div {
    style = "margin:1rem;padding:1rem;background:yellow;display:flex"
    add(renderHand(g.ph))
    add(renderHand(g.dh))
}

private fun renderHand(h: Hand) = document.create.div {
    style = "margin:1rem;padding:1rem;background:#DDDDDD"
    div { b { +h.name } }
    div {
        h.cards.map { div { it.name } }
    }
    div { b { +"${h.points} points" } }
}

Generalize tag type

It should be generalized tag interfaces to make easier to declare extension functions on generic tag types

Couldn't get updated value from text input

Environment: Kotlin JS 1.1.4-3 with kotlinx.html 0.6.4

What I did:

  1. Add a text input and add a button
  2. Click the button to retrieve the latest value from the input
  3. Can't get the updated value, always the original test text

I use the following javascript, it works as expected, document.getElementByID('TestInput').value

The code is as follows:
A bug or am I doing something wrong?

import kotlinx.html.*
import kotlinx.html.dom.create
import kotlinx.html.js.*
import org.w3c.dom.Element
import org.w3c.dom.events.Event
import kotlin.browser.*

fun onClick(e:Event){
    val element = document.getElementById("TestInput")
    window.alert(element?.getAttribute("value").toString())
}

fun main(args: Array<String>) {
    val root: Element = document.getElementById("root")!!

    val myDiv = document.create.div {
        input(InputType.text) {
            id="TestInput"
            value="test text"
        }
        button {
            +"Get input.value"
            onClickFunction=::onClick
        }
    }

    root.appendChild(myDiv)
}

input: add support for minlength

I see there is a maxLength property for HTML5's maxlength but I don't see a minLength property for HTML5's minlength. Can this be added?

script tag in stream mode escapes quotes

script(type = ScriptType.textJavaScript) { +"var str = 'some text';" } will result:

<script type="text/jscript">var str = 'some text';</script>

how to avoid quotation in this case?

type safe inline css

When I use inline css in an html or jsp file, IntelliJ gives me nice syntax coloring and autocompletion:
css-ide

Is there a type safe way to do inline css using kotlinx.html other than using a string? Or at least a way to get autocompletion and syntax coloring?

body {
    div {
        style = "background: yellow;border: solid thin blue"
    }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.