From 935d61324f295d552258c4a7a790d5cbfd2fb81c Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Fri, 30 Mar 2018 21:39:16 +0300 Subject: [PATCH] ShowWidget: Convert html to pango markup and render it. Instead of stipping all the html tags and just using the text in the label we could *try* converting it to pango markup which is a bit more flexible than plain text. The code was copied from Fractal. --- hammond-gtk/src/main.rs | 2 +- hammond-gtk/src/utils.rs | 83 +++++++++++++++++++++++++++++++++ hammond-gtk/src/widgets/show.rs | 12 +++-- 3 files changed, 91 insertions(+), 6 deletions(-) diff --git a/hammond-gtk/src/main.rs b/hammond-gtk/src/main.rs index a648f9b..d5b2b4e 100644 --- a/hammond-gtk/src/main.rs +++ b/hammond-gtk/src/main.rs @@ -20,7 +20,7 @@ extern crate lazy_static; extern crate log; extern crate chrono; -extern crate dissolve; +// extern crate dissolve; extern crate hammond_data; extern crate hammond_downloader; extern crate humansize; diff --git a/hammond-gtk/src/utils.rs b/hammond-gtk/src/utils.rs index 81a9bad..f7c438f 100644 --- a/hammond-gtk/src/utils.rs +++ b/hammond-gtk/src/utils.rs @@ -257,6 +257,49 @@ pub fn time_period_to_duration(time: i64, period: &str) -> Duration { } } +/// https://gitlab.gnome.org/World/fractal/blob/da016b252a0710ffd324469cd2059e3e090695eb/fractal-gtk/src/util.rs#L44-79 +/// Converts the input `&str` to pango format, replacing special characters +/// `&, < and >` and parses URLS to show as a link +/// +/// # Examples +/// +/// ``` +/// let m = markup("this is parsed"); +/// assert_eq!(&m, "this is parsed"); +/// +/// let m = markup("this is parsed"); +/// assert_eq!(&m, "this is <parsed>"); +/// +/// let m = markup(); +/// assert_eq!(&m, "with links: http://gnome.org "); +/// ``` +pub fn html_to_pango_markup(s: &str) -> String { + let mut out = String::from(s); + + out = String::from(out.trim()); + out = out.replace('&', "&"); + out = out.replace('<', "<"); + out = out.replace('>', ">"); + + let amp = "(&)"; + let domain = "[^\\s,)(\"]+"; + let param = format!("({amp}?\\w+(=[\\w._-]+)?)", amp = amp); + let params = format!("(\\?{param}*)*", param = param); + let hash = "(#[\\w._-]+)?"; + + let regex_str = format!( + "(https?://{domain}{params}{hash})", + domain = domain, + params = params, + hash = hash + ); + + let re = Regex::new(®ex_str).unwrap(); + out = String::from(re.replace_all(&out, "$0")); + + out +} + #[cfg(test)] mod tests { use super::*; @@ -327,4 +370,44 @@ mod tests { let id = 000000000; assert!(lookup_id(id).is_err()); } + + #[test] + fn test_markup() { + let markup = html_to_pango_markup; + let m = markup("this is parsed"); + assert_eq!(&m, "this is parsed"); + + let m = markup("this is parsed"); + assert_eq!(&m, "this is <span>parsed</span>"); + + let m = markup("this is &ssdf;"); + assert_eq!(&m, "this is &ssdf;"); + + let url = "http://url.com/test?param1¶m2=test¶m3#hashing"; + let m = markup(&format!("this is &ssdf; {}", url)); + assert_eq!( + &m, + &format!( + "this is &ssdf; {0}", + url.replace('&', "&") + ) + ); + + for l in &[ + ("with links: http://gnome.org :D", "http://gnome.org"), + ( + "with links: http://url.com/test.html&stuff :D", + "http://url.com/test.html&stuff", + ), + ] { + let m = markup(l.0); + assert_eq!( + &m, + &format!( + "with links: {0} :D", + l.1.replace('&', "&") + ) + ); + } + } } diff --git a/hammond-gtk/src/widgets/show.rs b/hammond-gtk/src/widgets/show.rs index ca5ca04..8415ad8 100644 --- a/hammond-gtk/src/widgets/show.rs +++ b/hammond-gtk/src/widgets/show.rs @@ -1,4 +1,4 @@ -use dissolve; +// use dissolve; use failure::Error; // use glib; use gtk; @@ -7,10 +7,11 @@ use open; use hammond_data::Podcast; use hammond_data::dbqueries; -use hammond_data::utils::replace_extra_spaces; +// use hammond_data::utils::replace_extra_spaces; use app::Action; -use utils::set_image_from_path; +use utils::{html_to_pango_markup, set_image_from_path}; +// use utils::set_image_from_path; use widgets::episode::episodes_listbox; use std::sync::Arc; @@ -120,8 +121,9 @@ impl ShowWidget { fn set_description(&self, text: &str) { // TODO: Temporary solution until we render html urls/bold/italic probably with // markup. - let desc = dissolve::strip_html_tags(text).join(" "); - self.description.set_text(&replace_extra_spaces(&desc)); + // let desc = dissolve::strip_html_tags(text).join(" "); + // self.description.set_text(&replace_extra_spaces(&desc)); + self.description.set_text(&html_to_pango_markup(text)); } /// Set scrolled window vertical adjustment.