summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSavagePeanut <sourcehut@lazytapir.com>2024-01-20 18:59:41 -0600
committerSavagePeanut <sourcehut@lazytapir.com>2024-01-20 18:59:41 -0600
commit5e8d9ccf2f28936fabf6d155b37347d91a4fd1c5 (patch)
tree6c5333ecc6a6dcc83d61708c369ebb25ccc33ac5
parent91987c153449ea8b8ecb55cbc5968669e35454cb (diff)
style mentions. 1.6
m---------.env/src/slidge-dev-helpers0
-rw-r--r--Cargo.lock2
-rw-r--r--Cargo.toml2
-rw-r--r--README.md5
-rw-r--r--src/matrix.rs15
-rw-r--r--src/parser.rs14
-rw-r--r--src/telegram.rs17
-rw-r--r--tests/test_matrix.py9
-rw-r--r--tests/test_telegram.py11
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
diff --git a/Cargo.lock b/Cargo.lock
index 11a6bbd..050d891 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -175,7 +175,7 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "slidge-style-parser"
-version = "0.1.5"
+version = "0.1.6"
dependencies = [
"pyo3",
]
diff --git a/Cargo.toml b/Cargo.toml
index 6f274f5..bdd4b2d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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
diff --git a/README.md b/README.md
index c768844..4db6bf9 100644
--- a/README.md
+++ b/README.md
@@ -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"