pomu0325さんのブログ記事のコードを拡張してみた。
もともとのコードは「http://」ではじまる部分をリンクタグへ変換していたが、今回の拡張で次の二つの変換を追加した
def linkURL(s: String): NodeSeq = {
import util.matching._
class FirstMatch(pattern: Regex) {
def c2s(c: CharSequence): String = c.toString
def unapply(s: String) =
pattern.findFirstMatchIn(s) map {
case m => (c2s(m.before), m.matched, c2s(m.after))
}
}
val link = new FirstMatch("""http://[\d\w\-\./%?=#]+""".r)
val reply = new FirstMatch("""@[a-zA-Z0-9]+""".r)
val hashtag = new FirstMatch("""#[a-zA-Z0-9]+""".r)
s match {
case link(before, s, after) =>
linkURL(before) ++ <a href={s}>{xml.Text(s)}</a> ++ linkURL(after)
case reply(before, s, after) =>
val href = "http://twitter.com/"+s.drop(1)
linkURL(before) ++ <a href={href}>{xml.Text(s)}</a> ++ linkURL(after)
case hashtag(before, s, after) =>
val href = "/?q="+Helpers.urlEncode(s)
linkURL(before) ++ <a href={href}>{xml.Text(s)}</a> ++ linkURL(after)
case s => xml.Text(s)
}
}
これはさらに次のように拡張できる。次の例はTwitterのAPIが返す文字列がhtmlエンコードされているのを安全に戻している。
def linkURL(s: String): NodeSeq = {
import util.matching._
class FirstMatch(pattern: Regex) {
def c2s(c: CharSequence): String = c.toString
def unapply(s: String) =
pattern.findFirstMatchIn(s) map {
case m => (c2s(m.before), m.matched, c2s(m.after))
}
}
val link = new FirstMatch("""http://[\d\w\-\./%?=#]+""".r)
val reply = new FirstMatch("""@[a-zA-Z0-9]+""".r)
val hashtag = new FirstMatch("""#[a-zA-Z0-9]+""".r)
val amp = new FirstMatch("&".r)
val lt = new FirstMatch("<".r)
val gt = new FirstMatch(">".r)
val quote = new FirstMatch(""".r)
s match {
case link(before, s, after) =>
linkURL(before) ++ <a href={s}>{xml.Text(s)}</a> ++ linkURL(after)
case reply(before, s, after) =>
val href = "http://twitter.com/"+s.drop(1)
linkURL(before) ++ <a href={href}>{xml.Text(s)}</a> ++ linkURL(after)
case hashtag(before, s, after) =>
val href = "/?q="+Helpers.urlEncode(s)
linkURL(before) ++ <a href={href}>{xml.Text(s)}</a> ++ linkURL(after)
case lt(before,_,after) =>
linkURL(before) ++ xml.Text("<") ++ linkURL(after)
case gt(before,_,after) =>
linkURL(before) ++ xml.Text(">") ++ linkURL(after)
case quote(before,_,after) =>
linkURL(before) ++ xml.Text("\"") ++ linkURL(after)
case amp(before,_,after) =>
linkURL(before) ++ xml.Text("&") ++ linkURL(after)
case s => xml.Text(s)
}
}