Display bold/italic/monospace message formating, improve message-to-markup parsing

fixes #433
fixes #442
This commit is contained in:
fiaxh 2018-10-23 22:33:19 +02:00
parent 6b7ef800f5
commit 006e25aab8
2 changed files with 58 additions and 35 deletions

View file

@ -60,10 +60,11 @@ public class MessageItemWidgetGenerator : WidgetGenerator, Object {
if (message_item.message.body.has_prefix("/me")) { if (message_item.message.body.has_prefix("/me")) {
markup_text = markup_text.substring(3); markup_text = markup_text.substring(3);
} }
markup_text = Markup.escape_text(markup_text);
if (conversation.type_ == Conversation.Type.GROUPCHAT) { if (conversation.type_ == Conversation.Type.GROUPCHAT) {
markup_text = Util.make_word_bold_markup(markup_text, conversation.nickname); markup_text = Util.parse_add_markup(markup_text, conversation.nickname, true, true);
} else {
markup_text = Util.parse_add_markup(markup_text, null, true, true);
} }
if (message_item.message.body.has_prefix("/me")) { if (message_item.message.body.has_prefix("/me")) {
@ -73,8 +74,6 @@ public class MessageItemWidgetGenerator : WidgetGenerator, Object {
label.style_updated.connect(() => update_me_style(stream_interactor, message.real_jid ?? message.from, display_name, conversation.account, label, markup_text)); label.style_updated.connect(() => update_me_style(stream_interactor, message.real_jid ?? message.from, display_name, conversation.account, label, markup_text));
} }
markup_text = Util.make_link_markup(markup_text);
label.label = markup_text; label.label = markup_text;
return label; return label;
} }

View file

@ -138,39 +138,63 @@ public static bool is_24h_format() {
return settings_format == "24h" || p_format == " "; return settings_format == "24h" || p_format == " ";
} }
public static string make_word_bold_markup(string s, string word) { public static string parse_add_markup(string s_, string? highlight_word, bool parse_links, bool parse_text_markup, bool already_escaped_ = false) {
string ret = s; string s = s_;
int elongated_by = 0; bool already_escaped = already_escaped_;
Regex highlight_regex = new Regex("\\b" + Regex.escape_string(word.down()) + "\\b");
MatchInfo match_info;
string markup_text_bak = s.down();
highlight_regex.match(markup_text_bak, 0, out match_info);
for (; match_info.matches(); match_info.next()) {
int start, end;
match_info.fetch_pos(0, out start, out end);
ret = ret[0:start+elongated_by] + "<b>" + ret[start+elongated_by:end+elongated_by] + "</b>" + ret[end+elongated_by:ret.length];
elongated_by += 7;
}
markup_text_bak += ""; // We need markup_text_bak to live until here because url_regex.match does not copy the string
return ret;
}
public static string make_link_markup(string s) { if (parse_links) {
string ret = s;
Regex url_regex = new Regex("""(?i)\b((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»]))"""); Regex url_regex = new Regex("""(?i)\b((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»]))""");
int elongated_by = 0;
MatchInfo match_info; MatchInfo match_info;
string markup_text_bak = ret.down(); url_regex.match(s.down(), 0, out match_info);
url_regex.match(markup_text_bak, 0, out match_info); if (match_info.matches()) {
for (; match_info.matches(); match_info.next()) {
int start, end; int start, end;
match_info.fetch_pos(0, out start, out end); match_info.fetch_pos(0, out start, out end);
string link = ret[start+elongated_by:end+elongated_by]; string link = s[start:end];
ret = ret[0:start+elongated_by] + "<a href=\"" + link + "\">" + link + "</a>" + ret[end+elongated_by:ret.length]; return parse_add_markup(s[0:start], highlight_word, parse_links, parse_text_markup, already_escaped) +
elongated_by += 15 + link.length; "<a href=\"" + Markup.escape_text(link) + "\">" + parse_add_markup(link, highlight_word, false, false, already_escaped) + "</a>" +
parse_add_markup(s[end:s.length], highlight_word, parse_links, parse_text_markup, already_escaped);
} }
markup_text_bak += ""; // We need markup_text_bak to live until here because url_regex.match does not copy the string }
return ret;
if (!already_escaped) {
s = Markup.escape_text(s);
already_escaped = true;
}
if (highlight_word != null) {
Regex highlight_regex = new Regex("\\b" + Regex.escape_string(highlight_word.down()) + "\\b");
MatchInfo match_info;
highlight_regex.match(s.down(), 0, out match_info);
if (match_info.matches()) {
int start, end;
match_info.fetch_pos(0, out start, out end);
return parse_add_markup(s[0:start], highlight_word, parse_links, parse_text_markup, already_escaped) +
"<b>" + s[start:end] + "</b>" +
parse_add_markup(s[end:s.length], highlight_word, parse_links, parse_text_markup, already_escaped);
}
}
if (parse_text_markup) {
string[] markup_string = new string[]{"`", "_", "*"};
string[] convenience_tag = new string[]{"tt", "i", "b"};
for (int i = 0; i < markup_string.length; i++) {
Regex regex = new Regex(Regex.escape_string(markup_string[i]) + ".+" + Regex.escape_string(markup_string[i]));
MatchInfo match_info;
regex.match(s.down(), 0, out match_info);
if (match_info.matches()) {
int start, end;
match_info.fetch_pos(0, out start, out end);
start += markup_string[i].length;
end -= markup_string[i].length;
return parse_add_markup(s[0:start], highlight_word, parse_links, parse_text_markup, already_escaped) +
@"<$(convenience_tag[i])>" + s[start:end] + @"</$(convenience_tag[i])>" +
parse_add_markup(s[end:s.length], highlight_word, parse_links, parse_text_markup, already_escaped);
}
}
}
return s;
} }
} }