diff --git a/.gitignore b/.gitignore index 35b4a7f..fbd064a 100644 --- a/.gitignore +++ b/.gitignore @@ -45,3 +45,4 @@ bin/ .kotlin kotlin-js-store gradle.properties +.idea diff --git a/build.gradle.kts b/build.gradle.kts index 7c81767..58a523b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,7 +8,7 @@ plugins { } group = "nl.astraeus" -version = "1.1.0" +version = "2.0.0" repositories { mavenCentral() diff --git a/src/commonMain/kotlin/nl/astraeus/markdown/parser/Markdown.kt b/src/commonMain/kotlin/nl/astraeus/markdown/parser/Markdown.kt index 5e9fce0..fd9aadd 100644 --- a/src/commonMain/kotlin/nl/astraeus/markdown/parser/Markdown.kt +++ b/src/commonMain/kotlin/nl/astraeus/markdown/parser/Markdown.kt @@ -1,9 +1,16 @@ package nl.astraeus.markdown.parser +data class ListItem( + val text: String, + val order: Int, + val indentation: Int = 0 +) + data class CheckboxItem( val line: Int, val checked: Boolean, val text: String, + val indentation: Int = 0 ) sealed class MarkdownPart { @@ -66,7 +73,7 @@ sealed class MarkdownPart { ) : MarkdownPart() data class UnorderedList( - val lines: List>, + val lines: List, ) : MarkdownPart() data class CheckboxList( @@ -74,7 +81,7 @@ sealed class MarkdownPart { ) : MarkdownPart() data class OrderedList( - val lines: List, + val lines: List, ) : MarkdownPart() data class CodeBlock( diff --git a/src/commonMain/kotlin/nl/astraeus/markdown/parser/Parser.kt b/src/commonMain/kotlin/nl/astraeus/markdown/parser/Parser.kt index ac4a2cd..804932f 100644 --- a/src/commonMain/kotlin/nl/astraeus/markdown/parser/Parser.kt +++ b/src/commonMain/kotlin/nl/astraeus/markdown/parser/Parser.kt @@ -11,17 +11,22 @@ enum class MarkdownType { } fun markdown(text: String): List { - val lines = text.lines() + val lines: MutableList = text.lines().toMutableList() val parts = mutableListOf() var language = "" var type = MarkdownType.PARAGRAPH var listIndex = 1 var checkboxLine = 0 + var indentation = 0 var index = 0 val buffer = StringBuilder() var checkboxList = mutableListOf() + if (!lines.isEmpty() && lines.last().isNotEmpty()) { + lines.add("") + } + fun parseBuffer() { if (buffer.isNotBlank()) { parts.addAll(handleBuffer(type, buffer.toString(), language)) @@ -46,7 +51,7 @@ fun markdown(text: String): List { || line.startsWith("#.") ) { buffer.append("\n") - buffer.append(line.substring(2)) + buffer.append(rawLine) } else { buffer.append(" ") buffer.append(line) @@ -56,7 +61,7 @@ fun markdown(text: String): List { type == MarkdownType.CHECKBOX_LIST -> { if (line.isBlank()) { if (buffer.isNotBlank()) { - addCheckbox(checkboxList, checkboxLine, buffer) + addCheckbox(checkboxList, checkboxLine, buffer, indentation) } parts.add(MarkdownPart.CheckboxList(checkboxList)) checkboxList = mutableListOf() @@ -64,10 +69,11 @@ fun markdown(text: String): List { continue } else if (line.startsWith("- [ ]") || line.startsWith("- [x]")) { if (buffer.isNotBlank()) { - addCheckbox(checkboxList, checkboxLine, buffer) + addCheckbox(checkboxList, checkboxLine, buffer, indentation) } checkboxLine = index buffer.append(line) + indentation = rawLine.countSpaces() } else { buffer.append(" ") buffer.append(line) @@ -133,7 +139,7 @@ fun markdown(text: String): List { parseBuffer() type = MarkdownType.ORDERED_LIST listIndex = 2 - buffer.append(line.substring(2)) + buffer.append(rawLine) } line.startsWith("- [ ]") || line.startsWith("- [x]") -> { @@ -141,6 +147,7 @@ fun markdown(text: String): List { type = MarkdownType.CHECKBOX_LIST checkboxLine = index buffer.append(line) + indentation = rawLine.countSpaces() } line.startsWith("- ") || line.startsWith("* ") -> { @@ -189,14 +196,14 @@ fun markdown(text: String): List { index++ } - if (type == MarkdownType.CHECKBOX_LIST) { - if (buffer.isNotBlank()) { - addCheckbox(checkboxList, checkboxLine, buffer) - } - parts.add(MarkdownPart.CheckboxList(checkboxList)) - } else { - parseBuffer() - } + /* if (type == MarkdownType.CHECKBOX_LIST) { + if (buffer.isNotBlank()) { + addCheckbox(checkboxList, checkboxLine, buffer, indentation) + } + parts.add(MarkdownPart.CheckboxList(checkboxList)) + } else { + parseBuffer() + }*/ return parts } @@ -204,14 +211,16 @@ fun markdown(text: String): List { private fun addCheckbox( checkboxList: MutableList, index: Int, - buffer: StringBuilder + buffer: StringBuilder, + indentation: Int = 0 ) { if (buffer.length >= 5) { checkboxList.add( CheckboxItem( index, buffer.startsWith("- [x]"), - buffer.substring(5).trim() + buffer.substring(5).trim(), + indentation ) ) } else { @@ -248,17 +257,20 @@ private fun handleBuffer( } MarkdownType.ORDERED_LIST -> { - listOf(MarkdownPart.OrderedList(text.lines())) + val lines = text.lines() + val list = mutableListOf() + + parseList(lines, list) + + listOf(MarkdownPart.OrderedList(list)) } MarkdownType.UNORDERED_LIST -> { val lines = text.lines() - val list = mutableListOf>() + val list = mutableListOf() + + parseList(lines, list) - for (line in lines) { - val indent: Int = line.countSpaces() - list.add((indent / 2) to line.substring(indent + 2)) - } listOf(MarkdownPart.UnorderedList(list)) } @@ -270,3 +282,23 @@ private fun handleBuffer( parseTable(text) } } + +private fun parseList( + lines: List, + list: MutableList +) { + val orderMap = mutableMapOf() + + for (line in lines) { + val indent: Int = line.countSpaces() + val order = orderMap.getOrPut(indent) { 1 } + list.add( + ListItem( + line.substring(indent + 2), + order, + indent + ) + ) + orderMap[indent] = order + 1 + } +} diff --git a/src/commonTest/kotlin/nl/astraeus/markdown/parser/ParseTest.kt b/src/commonTest/kotlin/nl/astraeus/markdown/parser/ParseTest.kt index 646b8a9..618a28f 100644 --- a/src/commonTest/kotlin/nl/astraeus/markdown/parser/ParseTest.kt +++ b/src/commonTest/kotlin/nl/astraeus/markdown/parser/ParseTest.kt @@ -68,6 +68,22 @@ class ParseTest { printMarkdownParts(md) } + @Test + fun testUnorderedList2() { + val input = """ + - First + - Second + - 2.1 + - 2.1.1 + - 2.1.1 + - 3 + """.trimIndent() + + val md = markdown(input) + + printMarkdownParts(md) + } + @Test fun testUnorderedListAlternative() { val input = """ @@ -115,6 +131,9 @@ class ParseTest { More text -. Second More text + -. Sub 1 + -. Sub 2 + -. Third Another paragraph """.trimIndent() @@ -204,6 +223,33 @@ class ParseTest { printMarkdownParts(md) } + @Test + fun testCheckboxList4() { + val input = """ + Dit is een text + + - [ ] Not checked, + with some more text here + - [x] Checked! + - [x] Checked, + text it! + + Nog 1: + + - [ ] Not checked, + with some more text here + - [x] Checked! + - [x] Checked, + text it! + + Meer text + """.trimIndent() + + val md = markdown(input) + + printMarkdownParts(md) + } + @Test fun testCheckboxListError() {