1
0
mirror of https://github.com/tateisu/SubwayTooter synced 2025-01-31 11:04:56 +01:00

(Misskey)strike マークダウンに対応

This commit is contained in:
tateisu 2018-12-04 06:53:05 +09:00
parent 87b13a9cb8
commit 4db2b63916

View File

@ -8,6 +8,7 @@ import android.text.Spanned
import android.text.style.BackgroundColorSpan import android.text.style.BackgroundColorSpan
import android.text.style.ForegroundColorSpan import android.text.style.ForegroundColorSpan
import android.text.style.RelativeSizeSpan import android.text.style.RelativeSizeSpan
import android.text.style.StrikethroughSpan
import android.util.SparseArray import android.util.SparseArray
import android.util.SparseBooleanArray import android.util.SparseBooleanArray
import jp.juggler.subwaytooter.ActMain import jp.juggler.subwaytooter.ActMain
@ -31,8 +32,7 @@ import java.util.regex.Pattern
import uk.co.chrisjenx.calligraphy.CalligraphyTypefaceSpan import uk.co.chrisjenx.calligraphy.CalligraphyTypefaceSpan
// import uk.co.chrisjenx.calligraphy.CalligraphyTypefaceSpan // import uk.co.chrisjenx.calligraphy.CalligraphyTypefaceSpan
private fun fontSpan(typeFace:Typeface):Any = private fun fontSpan(tf : Typeface) : Any = CalligraphyTypefaceSpan(tf)
CalligraphyTypefaceSpan(typeFace)
// 配列中の要素をラムダ式で変換して、戻り値が非nullならそこで処理を打ち切る // 配列中の要素をラムダ式で変換して、戻り値が非nullならそこで処理を打ち切る
private inline fun <T, V> Array<out T>.firstNonNull(predicate : (T) -> V?) : V? { private inline fun <T, V> Array<out T>.firstNonNull(predicate : (T) -> V?) : V? {
@ -546,8 +546,6 @@ object MisskeyMarkdownDecoder {
s.replace(reStartEmptyLines, "") s.replace(reStartEmptyLines, "")
.replace(reEndEmptyLines, "") .replace(reEndEmptyLines, "")
// 装飾つきテキストの出力時に使うデータの集まり // 装飾つきテキストの出力時に使うデータの集まり
internal class SpanOutputEnv( internal class SpanOutputEnv(
val options : DecodeOptions, val options : DecodeOptions,
@ -696,21 +694,21 @@ object MisskeyMarkdownDecoder {
mixColor(Color.GRAY, 0xff0080), mixColor(Color.GRAY, 0xff0080),
mixColor(Color.GRAY, 0x8000ff) mixColor(Color.GRAY, 0x8000ff)
) )
// ノード種別とレンダリング関数 // ノード種別とレンダリング関数
enum class NodeType(val render : SpanOutputEnv.(Node) -> Unit) { enum class NodeType(val render : SpanOutputEnv.(Node) -> Unit) {
TEXT({ TEXT({
appendText(it.args[0], decodeEmoji = true) appendText(it.args[0], decodeEmoji = true)
}), }),
EMOJI({ EMOJI({
val code = it.args[0] val code = it.args[0]
if(code.isNotEmpty()) { if(code.isNotEmpty()) {
appendText(":$code:", decodeEmoji = true) appendText(":$code:", decodeEmoji = true)
} }
}), }),
MENTION({ MENTION({
val username = it.args[0] val username = it.args[0]
val host = it.args[1] val host = it.args[1]
@ -761,7 +759,7 @@ object MisskeyMarkdownDecoder {
) )
} }
}), }),
HASHTAG({ HASHTAG({
val linkHelper = linkHelper val linkHelper = linkHelper
val tag = it.args[0] val tag = it.args[0]
@ -847,6 +845,11 @@ object MisskeyMarkdownDecoder {
spanList.addLast(start, sb.length, fontSpan(font_bold)) spanList.addLast(start, sb.length, fontSpan(font_bold))
}), }),
STRIKE({
val start = this.start
fireRenderChildNodes(it)
spanList.addLast(start, sb.length, StrikethroughSpan())
}),
MOTION({ MOTION({
val start = this.start val start = this.start
fireRenderChildNodes(it) fireRenderChildNodes(it)
@ -977,46 +980,66 @@ object MisskeyMarkdownDecoder {
; ;
companion object { companion object {
// あるノードが内部に持てるノード種別のマップ // あるノードが内部に持てるノード種別のマップ
val mapAllowInside = HashMap<NodeType, HashSet<NodeType>>().apply { val mapAllowInside = HashMap<NodeType, HashSet<NodeType>>().apply {
fun <T> hashSetOf(vararg values : T) = HashSet<T>().apply { addAll(values) } fun <T> hashSetOf(vararg values : T) = HashSet<T>().apply { addAll(values) }
infix fun NodeType.wraps(inner : HashSet<NodeType>) = put(this, inner) infix fun NodeType.wraps(inner : HashSet<NodeType>) = put(this, inner)
// EMOJI, HASHTAG, MENTION, CODE_BLOCK, QUOTE_INLINE, SEARCH 等はマークダウン要素のネストを許可しない
BIG wraps BIG wraps
hashSetOf(EMOJI, HASHTAG, MENTION) hashSetOf(EMOJI, HASHTAG, MENTION, STRIKE)
BOLD wraps BOLD wraps
hashSetOf(EMOJI, HASHTAG, MENTION, URL, LINK) hashSetOf(EMOJI, HASHTAG, MENTION, URL, LINK, STRIKE)
MOTION wraps
STRIKE wraps
hashSetOf(EMOJI, HASHTAG, MENTION, URL, LINK, BOLD) hashSetOf(EMOJI, HASHTAG, MENTION, URL, LINK, BOLD)
MOTION wraps
hashSetOf(EMOJI, HASHTAG, MENTION, URL, LINK, BOLD, STRIKE)
LINK wraps LINK wraps
hashSetOf(EMOJI, MOTION, BIG, BOLD) hashSetOf(EMOJI, MOTION, BIG, BOLD, STRIKE)
TITLE wraps TITLE wraps
hashSetOf(EMOJI, HASHTAG, MENTION, URL, LINK, BIG, BOLD, MOTION, CODE_INLINE) hashSetOf(
EMOJI, HASHTAG, MENTION, URL, LINK, BIG, BOLD, STRIKE,
MOTION, CODE_INLINE
)
CENTER wraps CENTER wraps
hashSetOf(EMOJI, HASHTAG, MENTION, URL, LINK, BIG, BOLD, MOTION, CODE_INLINE)
QUOTE_BLOCK wraps
hashSetOf( hashSetOf(
EMOJI, HASHTAG, MENTION, URL, LINK, BIG, BOLD, MOTION, CODE_INLINE, EMOJI, HASHTAG, MENTION, URL, LINK, BIG, BOLD, STRIKE,
CODE_BLOCK, QUOTE_INLINE, SEARCH, TITLE, CENTER, QUOTE_BLOCK MOTION, CODE_INLINE
)
ROOT wraps
hashSetOf(
EMOJI, HASHTAG, MENTION, URL, LINK, BIG, BOLD, MOTION, CODE_INLINE,
CODE_BLOCK, QUOTE_INLINE, SEARCH, TITLE, CENTER, QUOTE_BLOCK
) )
// all except ROOT,TEXT
val allSet = hashSetOf(
CODE_BLOCK, QUOTE_INLINE, SEARCH,
EMOJI, HASHTAG, MENTION, URL, LINK, BIG, BOLD, STRIKE,
MOTION, CODE_INLINE,
TITLE, CENTER, QUOTE_BLOCK
)
QUOTE_BLOCK wraps allSet
ROOT wraps allSet
} }
} }
} }
// マークダウン要素 // マークダウン要素
class Node( class Node(
val type : NodeType, // ノード種別 val type : NodeType, // ノード種別
val args : Array<String> = emptyArray(), // 引数 val args : Array<String> = emptyArray(), // 引数
parentNode : Node? parentNode : Node?
) { ) {
val childNodes = LinkedList<Node>() val childNodes = LinkedList<Node>()
internal val quoteNest : Int = (parentNode?.quoteNest ?: 0) + when(type) { internal val quoteNest : Int = (parentNode?.quoteNest ?: 0) + when(type) {
@ -1034,6 +1057,7 @@ object MisskeyMarkdownDecoder {
val startInside : Int, // 内部範囲の開始位置 val startInside : Int, // 内部範囲の開始位置
private val lengthInside : Int // 内部範囲の終了位置 private val lengthInside : Int // 内部範囲の終了位置
) { ) {
val endInside : Int val endInside : Int
get() = startInside + lengthInside get() = startInside + lengthInside
} }
@ -1186,6 +1210,15 @@ object MisskeyMarkdownDecoder {
} }
} }
// Strike ~~...~~
addParser(
"~"
, simpleParser(
Pattern.compile("""\A~~(.+?)~~""")
, NodeType.STRIKE
)
)
// Quote "..." // Quote "..."
addParser( addParser(
"\"" "\""
@ -1373,7 +1406,7 @@ object MisskeyMarkdownDecoder {
addParser("検Ss", searchParser) addParser("検Ss", searchParser)
addParser("?", linkParser) addParser("?", linkParser)
addParser("@", { addParser("@", {
val matcher = remainMatcher(TootAccount.reMention) val matcher = remainMatcher(TootAccount.reMention)
when { when {