From 4c23bdc1ad3fe6ab70a2a286f347657880266734 Mon Sep 17 00:00:00 2001 From: usbharu Date: Wed, 13 Nov 2024 16:39:28 +0900 Subject: [PATCH] wip --- .../kotlin/dev/usbharu/markdown/Lexer.kt | 37 ++++++++++++---- .../kotlin/dev/usbharu/markdown/Token.kt | 4 +- .../kotlin/dev/usbharu/markdown/LexerTest.kt | 42 +++++++++++++++++++ 3 files changed, 75 insertions(+), 8 deletions(-) diff --git a/library/src/commonMain/kotlin/dev/usbharu/markdown/Lexer.kt b/library/src/commonMain/kotlin/dev/usbharu/markdown/Lexer.kt index a7c7ff9..e982e60 100644 --- a/library/src/commonMain/kotlin/dev/usbharu/markdown/Lexer.kt +++ b/library/src/commonMain/kotlin/dev/usbharu/markdown/Lexer.kt @@ -50,6 +50,14 @@ class Lexer { next == 'h' -> url(next, iterator, tokens) next == '*' || next == '_' -> asterisk(iterator, next, tokens) + next == '!' -> { + if (iterator.peekOrNull() == '[') { + tokens.add(Exclamation) + } else { + tokens.add(Text("!")) + } + } + else -> { val lastToken = tokens.lastOrNull() if (lastToken is Text) { @@ -97,27 +105,42 @@ class Lexer { tokens: MutableList, ) { //todo httpにも対応 - //todo nextでみずにpeekでみて確認してからnextする hのあとにアスタリスク等が来たときに対応できない - val charIterator = "ttps://".iterator() + val charIterator = PeekableCharIterator("ttps://".toCharArray()) val urlBuilder = StringBuilder() urlBuilder.append(next) while (charIterator.hasNext() && iterator.hasNext()) { -// charIterator - val nextC = charIterator.next() - val nextC2 = iterator.next() - urlBuilder.append(nextC2) + val nextC = charIterator.peekOrNull() ?: return + val nextC2 = iterator.peekOrNull() ?: return if (nextC != nextC2) { tokens.add(Text(urlBuilder.toString())) return } + urlBuilder.append(nextC2) + charIterator.next() + iterator.next() } if (urlBuilder.length == 1) { tokens.add(Text(urlBuilder.toString())) //hだけのときはURLじゃないのでテキストとして追加 } else { - while (iterator.hasNext() && iterator.peekOrNull()?.isWhitespace() != true) { + while (iterator.hasNext() && (iterator.peekOrNull() + ?.isWhitespace() != true && iterator.peekOrNull() != ')') + ) { urlBuilder.append(iterator.next()) } tokens.add(Url(urlBuilder.toString())) + skipWhitespace(iterator) + val doubleQuotation = iterator.peekOrNull() + if (iterator.peekOrNull() == '"' || doubleQuotation == '”') { + iterator.next() + doubleQuotation!! + val titleBuilder = StringBuilder() + while (iterator.hasNext() && iterator.peekOrNull() != doubleQuotation && iterator.peekOrNull() != ')') { + titleBuilder.append(iterator.next()) + } + if (iterator.peekOrNull() == '"') { + iterator.next() + } + } } } diff --git a/library/src/commonMain/kotlin/dev/usbharu/markdown/Token.kt b/library/src/commonMain/kotlin/dev/usbharu/markdown/Token.kt index eed086b..a5947e5 100644 --- a/library/src/commonMain/kotlin/dev/usbharu/markdown/Token.kt +++ b/library/src/commonMain/kotlin/dev/usbharu/markdown/Token.kt @@ -23,4 +23,6 @@ data object SquareBracketEnd : Token() data object ParenthesesStart : Token() data object ParenthesesEnd : Token() data class Url(var url: String) : Token() -data class Asterisk(var count: Int, var char: Char) : Token() \ No newline at end of file +data class Asterisk(var count: Int, var char: Char) : Token() +data object Exclamation : Token() +data class UrlTitle(val title: String) : Token() \ No newline at end of file diff --git a/library/src/commonTest/kotlin/dev/usbharu/markdown/LexerTest.kt b/library/src/commonTest/kotlin/dev/usbharu/markdown/LexerTest.kt index 6f38bc3..7d4b03f 100644 --- a/library/src/commonTest/kotlin/dev/usbharu/markdown/LexerTest.kt +++ b/library/src/commonTest/kotlin/dev/usbharu/markdown/LexerTest.kt @@ -563,6 +563,48 @@ class LexerTest { assertContentEquals( listOf( + Text("h"), Asterisk(1, '*'), Text("a"), Asterisk(1, '*') + ), actual + ) + } + + @Test + fun 画像() { + val lexer = Lexer() + + val actual = lexer.lex("![alt](https://example.com)") + + println(actual) + + assertContentEquals( + listOf( + Exclamation, + SquareBracketStart, + Text("alt"), + SquareBracketEnd, + ParenthesesStart, + Url("https://example.com"), + ParenthesesEnd + ), actual + ) + } + + @Test + fun url3() { + val lexer = Lexer() + + val actual = lexer.lex("[alt](https://example.com)") + + println(actual) + + assertContentEquals( + listOf( + SquareBracketStart, + Text("alt"), + SquareBracketEnd, + ParenthesesStart, + Url("https://example.com"), + ParenthesesEnd ), actual ) }