Repository: ajalt/mordant (kotlin)

Issue:
Markdown table parsing fails on empty cells
Trying to print a markdown file that contains empty cells fails currently (mordant version 2.0.0-beta2). 
 
```kotlin
fun main() {
    val t = Terminal()
    t.println(Markdown("""
        | Test |
        |------|
        |      |
    """.trimIndent()))
}
```
The parser does not expect to only encounter whitespace.

```Java
Exception in thread "main" java.lang.IllegalArgumentException: fromIndex(1) > toIndex(0)
	at java.util.ArrayList.subListRangeCheck(ArrayList.java:1014)
	at java.util.ArrayList.subList(ArrayList.java:1004)
	at com.github.ajalt.mordant.markdown.MarkdownRenderer.innerInlines(MarkdownRenderer.kt:279)
	at com.github.ajalt.mordant.markdown.MarkdownRenderer.access$innerInlines(MarkdownRenderer.kt:59)
	at com.github.ajalt.mordant.markdown.MarkdownRenderer$parseTableRow$1.invoke(MarkdownRenderer.kt:316)
	at com.github.ajalt.mordant.markdown.MarkdownRenderer$parseTableRow$1.invoke(MarkdownRenderer.kt:312)
	at com.github.ajalt.mordant.table.SectionBuilderInstance.row(TableDslInstances.kt:96)
	at com.github.ajalt.mordant.markdown.MarkdownRenderer.parseTableRow(MarkdownRenderer.kt:312)
	at com.github.ajalt.mordant.markdown.MarkdownRenderer.access$parseTableRow(MarkdownRenderer.kt:59)
	at com.github.ajalt.mordant.markdown.MarkdownRenderer$parseStructure$7$3.invoke(MarkdownRenderer.kt:174)
	at com.github.ajalt.mordant.markdown.MarkdownRenderer$parseStructure$7$3.invoke(MarkdownRenderer.kt:171)
	at com.github.ajalt.mordant.table.TableBuilderInstance.body(TableDslInstances.kt:64)
	at com.github.ajalt.mordant.markdown.MarkdownRenderer$parseStructure$7.invoke(MarkdownRenderer.kt:171)
	at com.github.ajalt.mordant.markdown.MarkdownRenderer$parseStructure$7.invoke(MarkdownRenderer.kt:159)
	at com.github.ajalt.mordant.table.TableDslKt.table(TableDsl.kt:202)
	at com.github.ajalt.mordant.markdown.MarkdownRenderer.parseStructure(MarkdownRenderer.kt:159)
	at com.github.ajalt.mordant.markdown.MarkdownRenderer.parseFile(MarkdownRenderer.kt:87)
	at com.github.ajalt.mordant.markdown.MarkdownRenderer.render(MarkdownRenderer.kt:81)
	at com.github.ajalt.mordant.markdown.Markdown.document(Markdown.kt:25)
	at com.github.ajalt.mordant.markdown.Markdown.render(Markdown.kt:31)
	at com.github.ajalt.mordant.rendering.Widget$DefaultImpls.render$default(Widget.kt:8)
	at com.github.ajalt.mordant.terminal.Terminal.render(Terminal.kt:242)
	at com.github.ajalt.mordant.terminal.Terminal.println(Terminal.kt:201)
	at main(Main.kt:10)
```
I currently have to work around this issue, by putting an invisible character into empty cells.

Pull request:
Fixes #27

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f74d66449..a2cad1b29 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,12 @@
 
 ## Unreleased
 
+### Changed
+- Update Kotlin to 1.5.20
+
+### Fixed
+- Fixed exception thrown when parsing markdown tables with empty cells
+
 ## 2.0.0-beta2
 _2021-06-01_
 
diff --git a/build.gradle.kts b/build.gradle.kts
index 3a5fb1bca..74f182604 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,7 +1,7 @@
 import java.io.ByteArrayOutputStream
 
 plugins {
-    kotlin("jvm") version "1.5.10"
+    kotlin("jvm") version "1.5.20"
 }
 
 val VERSION_NAME: String by project
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 0f80bbf51..05679dc3c 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-bin.zip
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
diff --git a/mordant/src/commonMain/kotlin/com/github/ajalt/mordant/markdown/MarkdownRenderer.kt b/mordant/src/commonMain/kotlin/com/github/ajalt/mordant/markdown/MarkdownRenderer.kt
index c608bfbdc..95a5e30c2 100644
--- a/mordant/src/commonMain/kotlin/com/github/ajalt/mordant/markdown/MarkdownRenderer.kt
+++ b/mordant/src/commonMain/kotlin/com/github/ajalt/mordant/markdown/MarkdownRenderer.kt
@@ -305,7 +305,7 @@ internal class MarkdownRenderer(
 
     private fun dropWs(nodes: List<ASTNode>): Pair<Int, Int> {
         val drop = if (nodes.firstOrNull()?.type == MarkdownTokenTypes.WHITE_SPACE) 1 else 0
-        val dropLast = if (nodes.lastOrNull()?.type == MarkdownTokenTypes.WHITE_SPACE) 1 else 0
+        val dropLast = if (nodes.size > 1 && nodes.last().type == MarkdownTokenTypes.WHITE_SPACE) 1 else 0
         return drop to dropLast
     }
 


Test patch:
diff --git a/mordant/src/commonTest/kotlin/com/github/ajalt/mordant/markdown/MarkdownTest.kt b/mordant/src/commonTest/kotlin/com/github/ajalt/mordant/markdown/MarkdownTest.kt
index ccc87afb4..da8461ea3 100644
--- a/mordant/src/commonTest/kotlin/com/github/ajalt/mordant/markdown/MarkdownTest.kt
+++ b/mordant/src/commonTest/kotlin/com/github/ajalt/mordant/markdown/MarkdownTest.kt
@@ -726,6 +726,35 @@ LS
 └────────┴────────┴────────┘
 """)
 
+    @Test
+    @JsName("table_with_empty_cell")
+    fun `table with empty cell`() = doTest("""
+ | foo |
+ | --- |
+ |     |
+""", """
+┌─────┐
+│${bold(" foo ")}│
+╞═════╡
+│     │
+└─────┘
+""")
+
+    @Test
+    @JsName("table_with_empty_header_cell")
+    fun `table with empty header cell`() = doTest("""
+ |     |
+ | --- |
+ | baz |
+""", """
+┌─────┐
+│     │
+╞═════╡
+│ baz │
+└─────┘
+""")
+
+
     // https://github.github.com/gfm/#example-279
     @Test
     @JsName("task_list")