blob: d3c9d5d99ae038b482edb0e599308248509945ca (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
package moe.nea.blog.md
object ItalicsParser : InlineParser {
override fun detect(lookback: MarkdownFormat, rest: String): Boolean {
return (lookback is Whitespace || lookback is Begin) && "\\*+[^ ].*".toRegex().matches(rest)
}
override val specialSyntax: Set<Char>
get() = setOf('*')
override fun parse(parser: MarkdownParser, text: String): Pair<MarkdownFormat, String> {
var firstStarCount = 0
while (firstStarCount in text.indices) {
if (text[firstStarCount] != '*') break
firstStarCount++
}
if (firstStarCount < 1 || firstStarCount > 3) error("Invalid italics/bold sequence")
val isBold = firstStarCount >= 2
val isItalics = (firstStarCount % 2) == 1
val firstSequence = mutableListOf<MarkdownFormat>()
var remainingText = text.substring(firstStarCount)
var lastToken: MarkdownFormat = Begin() // TODO: dedicated begin token
while (remainingText.isNotEmpty()) {
val (element, next) = parser.parseInlineTextOnce(lastToken, remainingText)
remainingText = next
lastToken = element
firstSequence.add(element)
if (element !is Whitespace && next.startsWith("*")) break
}
var secondStarCount = 0
while (secondStarCount in remainingText.indices) {
if (remainingText[secondStarCount] != '*') break
secondStarCount++
}
if (secondStarCount > firstStarCount)
secondStarCount = firstStarCount
if (secondStarCount < 1) error("Invalid italics/bold sequence")
remainingText = remainingText.substring(secondStarCount)
var firstElement = parser.collapseInlineFormat(firstSequence, false)
if (secondStarCount == 2)
firstElement = Bold(firstElement)
if (secondStarCount == 1)
firstElement = Italics(firstElement)
if (secondStarCount == firstStarCount) {
return Pair(firstElement, remainingText)
}
val secondSequence = mutableListOf<MarkdownFormat>()
lastToken = Begin()
while (remainingText.isNotEmpty()) {
val (element, next) = parser.parseInlineTextOnce(lastToken, remainingText)
remainingText = next
lastToken = element
secondSequence.add(element)
if (element !is Whitespace && next.startsWith("*")) break
}
var thirdStarCount = 0
while (thirdStarCount in remainingText.indices) {
if (remainingText[thirdStarCount] != '*') break
thirdStarCount++
}
if (thirdStarCount > firstStarCount - secondStarCount)
thirdStarCount = firstStarCount
remainingText = remainingText.substring(thirdStarCount)
if (thirdStarCount != firstStarCount - secondStarCount) {
error("Invalid italics/bold sequence")
}
var secondElement = parser.collapseInlineFormat(secondSequence, false)
var combined: MarkdownFormat = FormatSequence(firstElement, secondElement)
if (thirdStarCount == 1)
combined = Italics(combined)
if (thirdStarCount == 2)
combined = Bold(combined)
return Pair(combined, remainingText)
}
}
|