MMM: Matrix handle parsing

This commit is contained in:
Natty 2023-10-26 21:23:59 +02:00
parent f34be3a104
commit 42e68fffcd
Signed by: natty
GPG Key ID: BF6CB659ADEE60EC
1 changed files with 33 additions and 22 deletions

View File

@ -29,6 +29,7 @@ use unicode_segmentation::UnicodeSegmentation;
pub enum MentionType { pub enum MentionType {
Community, Community,
User, User,
MatrixUser,
} }
impl MentionType { impl MentionType {
@ -36,6 +37,14 @@ impl MentionType {
match self { match self {
MentionType::Community => '!', MentionType::Community => '!',
MentionType::User => '@', MentionType::User => '@',
MentionType::MatrixUser => ':',
}
}
pub fn separator(&self) -> char {
match self {
MentionType::Community | MentionType::User => '@',
MentionType::MatrixUser => ':',
} }
} }
} }
@ -1460,7 +1469,6 @@ impl Context {
return Ok((plain_out, Token::PlainText(plain.into()))); return Ok((plain_out, Token::PlainText(plain.into())));
} }
let start = input;
let tags = one_of("@!"); let tags = one_of("@!");
let (input, mention_type) = map(tags, |c| match c { let (input, mention_type) = map(tags, |c| match c {
'@' => MentionType::User, '@' => MentionType::User,
@ -1474,29 +1482,28 @@ impl Context {
)(input)?; )(input)?;
let before = input; let before = input;
let (_, host) = map( let (_, host_opt) = opt(tuple((
opt(tuple(( one_of(if matches!(mention_type, MentionType::User) {
tag("@"), "@:"
map( } else {
recognize(many1(alt((alphanumeric1, recognize(one_of("-_.")))))), "@"
Span::into_fragment, }),
), map(
))), recognize(many1(alt((alphanumeric1, recognize(one_of("-_.")))))),
|maybe_tag_host| maybe_tag_host.map(|(_, host)| host), Span::into_fragment,
)(input)?; ),
)))(input)?;
let host = host.map(|h| h.trim_end_matches(|c| matches!(c, '.' | '-' | '_'))); // Promote tags with a colon separator to Matrix handles
let mention_type = if let Some((':', _)) = host_opt {
MentionType::MatrixUser
} else {
mention_type
};
let host =
host_opt.map(|(_, name)| name.trim_end_matches(|c| matches!(c, '.' | '-' | '_')));
let input = host.map(|c| before.slice(c.len() + 1..)).unwrap_or(before); let input = host.map(|c| before.slice(c.len() + 1..)).unwrap_or(before);
if let (input, Some(_)) =
peek(opt(tuple((recognize(tag(":")), alphanumeric1_unicode))))(input)?
{
return Ok((
input,
Token::PlainText(start.up_to(&input).into_fragment().into()),
));
}
Ok(( Ok((
input, input,
Token::Mention { Token::Mention {
@ -2182,7 +2189,11 @@ text</center>"#
assert_eq!( assert_eq!(
parse_full("@tag:domain.com"), parse_full("@tag:domain.com"),
Token::PlainText("@tag:domain.com".into()) Token::Mention {
mention_type: crate::MentionType::MatrixUser,
name: "tag".into(),
host: Some("domain.com".into())
},
); );
} }