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.
This commit is contained in:
Jordan Petridis 2018-03-30 21:39:16 +03:00
parent 10e016f2ea
commit 935d61324f
3 changed files with 91 additions and 6 deletions

View File

@ -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;

View File

@ -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 <span>parsed</span>");
/// assert_eq!(&m, "this is &lt;parsed&gt;");
///
/// let m = markup();
/// assert_eq!(&m, "with links: <a href=\"http://gnome.org\">http://gnome.org</a> ");
/// ```
pub fn html_to_pango_markup(s: &str) -> String {
let mut out = String::from(s);
out = String::from(out.trim());
out = out.replace('&', "&amp;");
out = out.replace('<', "&lt;");
out = out.replace('>', "&gt;");
let amp = "(&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(&regex_str).unwrap();
out = String::from(re.replace_all(&out, "<a href=\"$0\">$0</a>"));
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 <span>parsed</span>");
assert_eq!(&m, "this is &lt;span&gt;parsed&lt;/span&gt;");
let m = markup("this is &ssdf;");
assert_eq!(&m, "this is &amp;ssdf;");
let url = "http://url.com/test?param1&param2=test&param3#hashing";
let m = markup(&format!("this is &ssdf; {}", url));
assert_eq!(
&m,
&format!(
"this is &amp;ssdf; <a href=\"{0}\">{0}</a>",
url.replace('&', "&amp;")
)
);
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: <a href=\"{0}\">{0}</a> :D",
l.1.replace('&', "&amp;")
)
);
}
}
}

View File

@ -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.