diff options
| m--------- | .env/src/slidge-dev-helpers | 0 | ||||
| -rw-r--r-- | Cargo.lock | 2 | ||||
| -rw-r--r-- | Cargo.toml | 2 | ||||
| -rw-r--r-- | README.md | 5 | ||||
| -rw-r--r-- | src/matrix.rs | 15 | ||||
| -rw-r--r-- | src/parser.rs | 14 | ||||
| -rw-r--r-- | src/telegram.rs | 17 | ||||
| -rw-r--r-- | tests/test_matrix.py | 9 | ||||
| -rw-r--r-- | tests/test_telegram.py | 11 |
9 files changed, 54 insertions, 21 deletions
diff --git a/.env/src/slidge-dev-helpers b/.env/src/slidge-dev-helpers new file mode 160000 +Subproject 85ee4141062997317c90dda7bf0b6371a49d2d1 @@ -175,7 +175,7 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "slidge-style-parser" -version = "0.1.5" +version = "0.1.6" dependencies = [ "pyo3", ] @@ -1,6 +1,6 @@ [package] name = "slidge-style-parser" -version = "0.1.5" +version = "0.1.6" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -31,9 +31,10 @@ Most of them correspond to [XEP-0393: Message Styling](https://xmpp.org/extensio Methods: -format_for_telegram(body: String) -> (body: String, Vec<(format: String, offset: usize, length: usize, language: String)>) +format_for_telegram(body: String, mentions: Optional<(_, start, end_index_exclusive)>) + -> (body: String, Vec<(format: String, offset: usize, length: usize, language: String)>) -format_for_matrix(body: String) -> body: String +format_for_matrix(body: String, mentions: Optional<(mxid, start, end_index_exclusive)>) -> body: String format_body(body: String, new_tags: HashMap<String, (String, String)>) -> String diff --git a/src/matrix.rs b/src/matrix.rs index 47fa984..cebddfd 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -14,13 +14,14 @@ const MATRIX_FORMATS: &[(&'static str, (&'static str, &'static str))] = &[ ]; #[pyfunction] -pub fn format_for_matrix(body: String) -> PyResult<String> { +pub fn format_for_matrix(body: String, mentions: Option<Vec<(String, usize, usize)>>) -> PyResult<String> { let mut chars: Vec<char> = body.chars().collect(); if chars.len() < 1 { return Ok(body); } - let styles: Vec<(String, usize, usize, usize, usize)> = parse_with_limits(&chars, 0, chars.len() - 1, 0); + let mentions = mentions.unwrap_or(Vec::with_capacity(0)); + let styles: Vec<(String, usize, usize, usize, usize)> = parse_with_limits(&chars, 0, chars.len() - 1, 0); let mut tags: Vec<(usize, String, usize)> = Vec::with_capacity(styles.len() * 2); for (keyword, start, remove_start, end, remove_end) in styles { if MATRIX_FORMATS.iter().any(|&(k, _)| k == keyword) { @@ -30,14 +31,18 @@ pub fn format_for_matrix(body: String) -> PyResult<String> { .into_iter() .collect::<String>()) } else { - MATRIX_FORMATS.iter().find(|&&(k, _)| k == keyword).unwrap().1.0.clone().to_string() + MATRIX_FORMATS.iter().find(|&&(k, _)| k == keyword).unwrap().1.0.clone().to_owned() }; tags.push((start, opening_tag, remove_start)); - tags.push((end, MATRIX_FORMATS.iter().find(|&&(k, _)| k == keyword).unwrap().1.1.clone().to_string(), remove_end)); + tags.push((end, MATRIX_FORMATS.iter().find(|&&(k, _)| k == keyword).unwrap().1.1.clone().to_owned(), remove_end)); } else if keyword == ">>" || keyword == "```>" || keyword == "\\" { - tags.push((start, "".to_string(), start+1)); + tags.push((start, String::new(), start+1)); } } + for (mxid, start, end) in mentions { + tags.push((start, "<a href='https://matrix.to/#/".to_owned() + &mxid + "'>", start)); + tags.push((end, "</a>".to_owned(), end)); + } tags.sort_by(|a, b| b.0.cmp(&a.0)); diff --git a/src/parser.rs b/src/parser.rs index 0bf0f46..141aa7d 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -10,7 +10,7 @@ pub fn parse_with_limits(chars: &Vec<char>, start: usize, end: usize, depth: usi while index <= end { let c = chars[index]; if c == '\\' { - styles.push(("\\".to_string(), index, index + 1, index + 1, index + 1)); + styles.push(("\\".to_owned(), index, index + 1, index + 1, index + 1)); index += 2; continue; } @@ -18,13 +18,13 @@ pub fn parse_with_limits(chars: &Vec<char>, start: usize, end: usize, depth: usi if QUOTE_KEYWORDS.contains(&c) { if is_quote_start(chars, index, depth) { let to = seek_end_of_quote(chars, index, end, depth); - styles.push((">".to_string(), index, index + 1, to, to)); + styles.push((">".to_owned(), index, index + 1, to, to)); styles.append(&mut parse_with_limits(chars, index + 1, to, depth + 1)); index = to; continue; } if is_nested_quote(chars, index, depth) { - styles.push((">>".to_string(), index, index + 1, index + 1, index + 1)); + styles.push((">>".to_owned(), index, index + 1, index + 1, index + 1)); } index += 1; continue; @@ -40,9 +40,9 @@ pub fn parse_with_limits(chars: &Vec<char>, start: usize, end: usize, depth: usi Some(to) => { if to != end_of_line && is_quote_start(chars, index, depth) { let keyword = if end_of_line == index + 3 { - "```".to_string() + "```".to_owned() } else { - "```language".to_string() + "```language".to_owned() }; let remove_end = if depth > 0 && (to == end || to == chars.len()) { to @@ -69,7 +69,7 @@ pub fn parse_with_limits(chars: &Vec<char>, start: usize, end: usize, depth: usi match seek_end(chars, c, index + 2, 1, end) { Some(to) => { if to != index + 2 { - let keyword = "||".to_string(); + let keyword = "||".to_owned(); styles.push((keyword, index, index + 2, to, to + 2)); styles.append(&mut parse_with_limits(chars, index + 2, to - 1, depth)); } @@ -117,7 +117,7 @@ fn parse_quotes_in_code_block(chars: &Vec<char>, start: usize, end: usize, depth let c = chars[index]; if QUOTE_KEYWORDS.contains(&c) { if is_nested_quote(chars, index, depth) { - quotes.push(("```>".to_string(), index, index + 1, index + 1, index + 1)); + quotes.push(("```>".to_owned(), index, index + 1, index + 1, index + 1)); } index += 1; continue; diff --git a/src/telegram.rs b/src/telegram.rs index 481adec..c369744 100644 --- a/src/telegram.rs +++ b/src/telegram.rs @@ -13,11 +13,12 @@ const TELEGRAM_STYLES: &[(&'static str, &'static str)] = &[ ]; #[pyfunction] -pub fn format_for_telegram(body: String) -> PyResult<(String, Vec<(String, usize, usize, String)>)> { +pub fn format_for_telegram(body: String, mentions: Option<Vec<(String, usize, usize)>>) -> PyResult<(String, Vec<(String, usize, usize, String)>)> { let mut chars: Vec<char> = body.chars().collect(); if chars.len() < 1 { return Ok((body, Vec::with_capacity(0))); } + let mentions = mentions.unwrap_or(Vec::with_capacity(0)); let styles: Vec<(String, usize, usize, usize, usize)> = parse_with_limits(&chars, 0, chars.len() - 1, 0); let mut remove_tags: Vec<(usize, usize)> = Vec::with_capacity(styles.len() * 2); @@ -40,17 +41,23 @@ pub fn format_for_telegram(body: String) -> PyResult<(String, Vec<(String, usize .into_iter() .collect::<String>() } else { - "".to_string() + String::new() }; all_indexes.push(vec![*start, *remove_start - *start, *end, *remove_end - *end]); let last_index = all_indexes.len() - 1; - message_entities.push((true, last_index, TELEGRAM_STYLES.iter().find(|&&(k, _)| k == keyword).unwrap().1.to_string(), *start, language)); - message_entities.push((false, last_index, "".to_string(), *end, "".to_string())); + message_entities.push((true, last_index, TELEGRAM_STYLES.iter().find(|&&(k, _)| k == keyword).unwrap().1.to_owned(), *start, language)); + message_entities.push((false, last_index, String::new(), *end, String::new())); } else if keyword == "```>" || keyword == "\\" { all_indexes.push(vec![0, 0, *start, 1]); - message_entities.push((false, all_indexes.len() - 1, "".to_string(), *start, "".to_string())); + message_entities.push((false, all_indexes.len() - 1, String::new(), *start, String::new())); } } + for (_name, start, end) in mentions { + all_indexes.push(vec![start, 0, end, 0]); + let last_index = all_indexes.len() - 1; + message_entities.push((true, last_index, "mention".to_owned(), start, String::new())); + message_entities.push((false, last_index, String::new(), end, String::new())); + } message_entities.sort_by(|a, b| a.3.cmp(&b.3)); remove_tags.sort_by(|a, b| b.0.cmp(&a.0)); diff --git a/tests/test_matrix.py b/tests/test_matrix.py index edcfe37..29838bd 100644 --- a/tests/test_matrix.py +++ b/tests/test_matrix.py @@ -48,6 +48,15 @@ def test_basic(): formatted_body = "<span data-mx-spoiler>this message contains a spoiler</span>" assert(format_for_matrix(test) == formatted_body) +def test_basic_mention(): + test = "SavagePeanut _underline_" + formatted_body = "<a href='https://matrix.to/#/@SavagePeanut:example.org'>SavagePeanut</a> <em>underline</em>" + assert(format_for_matrix(test, [("@SavagePeanut:example.org", 0, 12)]) == formatted_body) + + test = "*bold* SavagePeanut" + formatted_body = "<strong>bold</strong> <a href='https://matrix.to/#/@SavagePeanut:example.org'>SavagePeanut</a>" + assert(format_for_matrix(test, [("@SavagePeanut:example.org", 7, 19)]) == formatted_body) + def test_empty(): test = "__ ** ~~ ``" formatted_body = "__ ** ~~ ``" diff --git a/tests/test_telegram.py b/tests/test_telegram.py index 0b3dbdc..b9f3e44 100644 --- a/tests/test_telegram.py +++ b/tests/test_telegram.py @@ -48,6 +48,17 @@ def test_basic(): styles = [('spoiler', 11, 10, '')] assert(format_for_telegram(test) == (formatted_body, styles)) +def test_basic_mention(): + test = "SavagePeanut _underline_" + formatted_body = "SavagePeanut underline" + styles = [('mention', 0, 12, ''), ('italics', 13, 9, '')] + assert(format_for_telegram(test, [("SavagePeanut", 0, 12)]) == (formatted_body, styles)) + + test = "*bold* SavagePeanut" + formatted_body = "bold SavagePeanut" + styles = [('bold', 0, 4, ''), ('mention', 5, 12, '')] + assert(format_for_telegram(test, [("SavagePeanut", 7, 19)]) == (formatted_body, styles)) + def test_quotes(): test = ">single" formatted_body = ">single" |
