varabyte / kobweb

A modern framework for full stack web apps in Kotlin, built upon Compose HTML
https://kobweb.varabyte.com
Apache License 2.0
1.53k stars 68 forks source link

Markdown handler works weirdly on images #503

Closed EgorBron closed 5 months ago

EgorBron commented 5 months ago

I'm trying to style images in Markdown files.

I know, a bit better way to do this is to write some CSS or define @InitSilk and set the selector. But, I decided to write a markdown handler for all images, as I found something similar (but for code blocks) in bitspittle's blog source.

For some reason it produces really weird code.

  1. Let's say I have an empty Kobweb app with package name net.website.

  2. I put an image to resources/public and created a Markdown file HelloWorld.md with such content:

    # Hello world
    
    ![greeting](/untitled.png)
  3. For all Markdown images I created a component:

    package net.website.components
    
    /* imports */
    
    @Composable
    fun MdImage(src: String, alt: String) {
      Image(src, alt, Modifier.width(50.percent))
    }
  4. Then, in site/build.gradle.kts I added the handler:

    // ...
    kobweb {
      markdown {
          handlers {
              img.set { image ->
                  "net.website.components.MdImage(\"${image.destination}\", \"${image.title}\")"
              }
          }
      }
    }
    // ...
  5. Finally, I ran kobweb run, but it throws an error:

    /* ...a huge stacktrace... */
    Found 3 error(s) and 0 warning(s). Please resolve errors to continue.
    
    1: file:///C:/projects/website/site/build/generated/kobweb/markdown/src/jsMain/kotlin/net/website/pages/HelloWorld.kt:15:69 Too many arguments for public fun MdImage(src: String, alt: String): Unit defined in net.website.components in file MdImage.kt
    2: file:///C:/projects/website/site/build/generated/kobweb/markdown/src/jsMain/kotlin/net/website/pages/HelloWorld.kt:17:51 @Composable invocations can only happen from the context of a @Composable function
    
    3: Execution failed for task ':site:compileKotlinJs'.
    > A failure occurred while executing org.jetbrains.kotlin.compilerRunner.GradleCompilerRunnerWithWorkers$GradleKotlinCompilerWorkAction      
     > Compilation error. See log for more details
  6. Now, I look to the generated HelloWorld.kt:

    package net.website.pages
    
    import androidx.compose.runtime.*
    import com.varabyte.kobweb.core.*
    import com.varabyte.kobwebx.markdown.*
    
    @Page
    @Composable
    fun HelloWorldPage() {
      CompositionLocalProvider(LocalMarkdownContext provides MarkdownContext("HelloWorld.md", /* there should be a frontmatter */)) {
          net.website.components.ArticleLayout {
              org.jetbrains.compose.web.dom.H1(attrs = { id("hello-world") }) {
                  org.jetbrains.compose.web.dom.Text("Hello world!")
              }
              org.jetbrains.compose.web.dom.P {
                  net.website.components.MdImage("/untitled.png", "null") {
                      org.jetbrains.compose.web.dom.Text("greeting") // what?! how?
                  }
              }
          }
      }
    }

    The image title (or alt text) was moved to composable trailing lambda as Text composable, while title became null!

  7. The expected output is the same code as in 6., but without trailing labmda after MdImage and null in img.title.

EgorBron commented 5 months ago

I also looked to Kobweb Gradle plugin, and, under the hood, it uses img.convention { } and img.children(). I tried this too, but nothing changed (except the img.children(), which is sometimes became null).