diff --git a/main/src/ui/conversation_summary/content_item_widget_factory.vala b/main/src/ui/conversation_summary/content_item_widget_factory.vala index 9e1edcb0..26b66664 100644 --- a/main/src/ui/conversation_summary/content_item_widget_factory.vala +++ b/main/src/ui/conversation_summary/content_item_widget_factory.vala @@ -60,10 +60,11 @@ public class MessageItemWidgetGenerator : WidgetGenerator, Object { if (message_item.message.body.has_prefix("/me")) { markup_text = markup_text.substring(3); } - markup_text = Markup.escape_text(markup_text); 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")) { @@ -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)); } - markup_text = Util.make_link_markup(markup_text); - label.label = markup_text; return label; } diff --git a/main/src/ui/util/helper.vala b/main/src/ui/util/helper.vala index 06715ad6..9472c965 100644 --- a/main/src/ui/util/helper.vala +++ b/main/src/ui/util/helper.vala @@ -138,39 +138,63 @@ public static bool is_24h_format() { return settings_format == "24h" || p_format == " "; } -public static string make_word_bold_markup(string s, string word) { - string ret = s; - int elongated_by = 0; - 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] + "" + ret[start+elongated_by:end+elongated_by] + "" + 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 parse_add_markup(string s_, string? highlight_word, bool parse_links, bool parse_text_markup, bool already_escaped_ = false) { + string s = s_; + bool already_escaped = already_escaped_; -public static string make_link_markup(string s) { - 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`!()\[\]{};:'".,<>?«»“”‘’]))"""); - int elongated_by = 0; - MatchInfo match_info; - string markup_text_bak = ret.down(); - url_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); - string link = ret[start+elongated_by:end+elongated_by]; - ret = ret[0:start+elongated_by] + "" + link + "" + ret[end+elongated_by:ret.length]; - elongated_by += 15 + link.length; + if (parse_links) { + 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`!()\[\]{};:'".,<>?«»“”‘’]))"""); + MatchInfo match_info; + url_regex.match(s.down(), 0, out match_info); + if (match_info.matches()) { + int start, end; + match_info.fetch_pos(0, out start, out end); + string link = s[start:end]; + return parse_add_markup(s[0:start], highlight_word, parse_links, parse_text_markup, already_escaped) + + "" + parse_add_markup(link, highlight_word, false, false, already_escaped) + "" + + 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) + + "" + s[start:end] + "" + + 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] + @"" + + parse_add_markup(s[end:s.length], highlight_word, parse_links, parse_text_markup, already_escaped); + } + } + } + + return s; } }