mirror of
https://github.com/tateisu/SubwayTooter
synced 2025-01-31 11:04:56 +01:00
(Misskey)strike マークダウンに対応
This commit is contained in:
parent
87b13a9cb8
commit
4db2b63916
@ -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 {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user