diff --git a/library/src/commonMain/kotlin/dev/usbharu/markdown/Lexer.kt b/library/src/commonMain/kotlin/dev/usbharu/markdown/Lexer.kt index d281ec0..dc6ad55 100644 --- a/library/src/commonMain/kotlin/dev/usbharu/markdown/Lexer.kt +++ b/library/src/commonMain/kotlin/dev/usbharu/markdown/Lexer.kt @@ -64,18 +64,13 @@ class Lexer { if (iterator.peekOrNull() == '[') { tokens.add(Exclamation) } else { - tokens.add(Text("!")) + addText(tokens, "!") } } else -> { - val lastToken = tokens.lastOrNull() - if (lastToken is Text) { - lastToken.text += next.toString() - } else { - tokens.add(Text(next.toString())) - } + addText(tokens, next.toString()) } } if (!inline && tokens.lastOrNull() !is Whitespace) { //行頭が空白の場合は一旦無視する @@ -105,13 +100,22 @@ class Lexer { return tokens } + private fun addText(tokens: MutableList, next: String) { + val lastToken = tokens.lastOrNull() + if (lastToken is Text) { + lastToken.text += next + } else { + tokens.add(Text(next)) + } + } + private fun codeblock( iterator: PeekableCharIterator, next: Char, tokens: MutableList, inCode: Boolean, codeBuffer: StringBuilder, - inline: Boolean + inline: Boolean, ): Boolean { var inCode1 = inCode if (iterator.peekOrNull() == next && !inline) { //行頭かつ次の文字が` @@ -157,20 +161,16 @@ class Lexer { } } else { - val codeBuilder = StringBuilder() - while (iterator.hasNext() && iterator.peekOrNull() != next) { - codeBuilder.append(iterator.next()) - } - if (iterator.hasNext() && iterator.next() == next) { //インラインコードブロックかと思ったら違った - if (codeBuilder.isEmpty()) { - tokens.add(Text("$next$next")) - } else { - tokens.add(InlineCodeBlock(codeBuilder.toString())) - } + val peekString = peekString(next, iterator) + if (peekString != null && peekString.isEmpty()) { + addText(tokens, "$next$next") + iterator.next() + } else if (peekString != null) { + tokens.add(InlineCodeBlock(peekString)) + iterator.skip(peekString.length + 1) } else { - tokens.add(Text(codeBuilder.insert(0, next).toString())) + addText(tokens, next.toString()) } - } return inCode1 } @@ -345,6 +345,19 @@ class Lexer { return count } + fun peekString(char: Char, iterator: PeekableCharIterator): String? { + var counter = 0 + val stringBuilder = StringBuilder() + while (iterator.peekOrNull(counter) != null && iterator.peekOrNull(counter) != char) { + stringBuilder.append(iterator.peekOrNull(counter)) + counter++ + } + if (iterator.peekOrNull(counter) == null) { + return null + } + return stringBuilder.toString() + } + fun collect(iterator: PeekableCharIterator): String { val char = mutableListOf() while (iterator.hasNext()) { diff --git a/library/src/commonMain/kotlin/dev/usbharu/markdown/PeekableIterator.kt b/library/src/commonMain/kotlin/dev/usbharu/markdown/PeekableIterator.kt index 3b0126e..42634e7 100644 --- a/library/src/commonMain/kotlin/dev/usbharu/markdown/PeekableIterator.kt +++ b/library/src/commonMain/kotlin/dev/usbharu/markdown/PeekableIterator.kt @@ -15,6 +15,12 @@ class PeekableCharIterator(private val charArray: CharArray) : Iterator { fun peekOrNull(): Char? = charArray.getOrNull(index) fun current(): Int = index + + fun peekOrNull(offset: Int): Char? = charArray.getOrNull(index + offset) + + fun skip(count: Int = 0) { + index += count + } } class PeekableStringIterator(private val list: List) : Iterator { diff --git a/library/src/commonTest/kotlin/dev/usbharu/markdown/LexerTest.kt b/library/src/commonTest/kotlin/dev/usbharu/markdown/LexerTest.kt index b6dfdae..55330a0 100644 --- a/library/src/commonTest/kotlin/dev/usbharu/markdown/LexerTest.kt +++ b/library/src/commonTest/kotlin/dev/usbharu/markdown/LexerTest.kt @@ -756,7 +756,7 @@ class LexerTest { assertContentEquals( listOf( - Text("```"), Text("`aiueo") + Text("````aiueo") ), actual ) } @@ -816,7 +816,12 @@ class LexerTest { assertContentEquals( listOf( - Text("aiueo"), Whitespace(1, ' '), Text("```abcd") + Text("aiueo"), + Whitespace(1, ' '), + Text("```abcd"), + Asterisk(1, '*'), + Text("a"), + Asterisk(1, '*') ), actual ) }