From 66e0a747f1b0d311162ae92603845862c0b0f98f Mon Sep 17 00:00:00 2001 From: yggverse Date: Sat, 12 Oct 2024 11:14:49 +0300 Subject: [PATCH] drop pango markup from parser, update api --- .../content/text/gemini/reader/parser/link.rs | 159 ++++++------------ 1 file changed, 55 insertions(+), 104 deletions(-) diff --git a/src/app/browser/window/tab/item/page/content/text/gemini/reader/parser/link.rs b/src/app/browser/window/tab/item/page/content/text/gemini/reader/parser/link.rs index d7d51cb9..f62cc512 100644 --- a/src/app/browser/window/tab/item/page/content/text/gemini/reader/parser/link.rs +++ b/src/app/browser/window/tab/item/page/content/text/gemini/reader/parser/link.rs @@ -1,58 +1,52 @@ -use gtk::glib::{ - gformat, markup_escape_text, GString, Regex, RegexCompileFlags, RegexMatchFlags, Uri, UriFlags, -}; +use gtk::glib::{GString, Regex, RegexCompileFlags, RegexMatchFlags, Uri, UriFlags}; pub struct Link { - // alt: Option, // [optional] alternative text - // date: Option, // [optional] date @TODO store in UnixTime? - // external: bool, // external link indicator - // link: GString, // original link, wanted for title tooltip - markup: GString, // pango markup with escaped special chars - // uri: Uri, // parsed link object (currently not in use) + pub alt: Option, + pub date: Option, // @TODO https://docs.gtk.org/glib/struct.Date.html + pub is_external: Option, + pub uri: Uri, } impl Link { - // Link structure parser - // line - gemtext subject to parse - // base - Uri object, required for: - // 1. relative to absolute address conversion - // 2. external links indication - // returns new Link struct or None - pub fn from(line: &str, base: &Uri) -> Option { - // Init struct members - // let mut alt: Option = None; - // let mut date: Option = None; - let external: bool; - let link: GString; - let markup: GString; - let uri: Uri; - - // Parse line - let parsed = Regex::split_simple( + pub fn from(line: &str, to_base: Option<&Uri>) -> Option { + // Define initial values + let mut alt = None; + let mut date = None; + let mut is_external = None; + + // Begin line parse + let regex = Regex::split_simple( r"^=>\s*([^\s]+)\s*(\d{4}-\d{2}-\d{2})?\s*(.+)?$", line, RegexCompileFlags::DEFAULT, RegexMatchFlags::DEFAULT, ); - // Address - match parsed.get(1) { - Some(address) => { - // Define original link value (used in titles or when alt is empty) - link = GString::from(address.as_str()); - // Links in document usually relative, make them absolute to base given - match Uri::resolve_relative(Some(&base.to_str()), address.as_str(), UriFlags::NONE) - { - Ok(resolved) => { - // Make URI parsed as always valid (no idea why does lib operate strings, not objects) - match Uri::parse(&resolved, UriFlags::NONE) { - Ok(object) => { - // Set external status - external = - object.host() != base.host() || object.port() != base.port(); - - // Set struct URI - uri = object; + // Detect address required to continue + let unresolved_address = regex.get(1)?; + + // Convert address to the valid URI + let uri = match to_base { + // Base conversion requested + Some(base_uri) => { + // Convert relative address to absolute + match Uri::resolve_relative( + Some(&base_uri.to_str()), + unresolved_address.as_str(), + UriFlags::NONE, + ) { + Ok(resolved_str) => { + // Try convert string to the valid URI + match Uri::parse(&resolved_str, UriFlags::NONE) { + Ok(resolved_uri) => { + // Change external status + is_external = Some( + resolved_uri.host() != base_uri.host() + || resolved_uri.port() != base_uri.port(), + ); + + // Result + resolved_uri } Err(_) => return None, } @@ -60,74 +54,31 @@ impl Link { Err(_) => return None, } } - None => return None, - } - - // Create link name based on external status, date and alt values - let mut name = Vec::new(); - - if external { - name.push("⇖".to_string()); - } + // Base resolve not requested + None => { + // Just try convert address to valid URI + match Uri::parse(&unresolved_address, UriFlags::NONE) { + Ok(unresolved_uri) => unresolved_uri, + Err(_) => return None, + } + } + }; // Date - if let Some(this) = parsed.get(2) { - // date = Some(GString::from(this.to_string())); - name.push(this.to_string()); + if let Some(value) = regex.get(2) { + date = Some(GString::from(value.as_str())) } // Alt - match parsed.get(3) { - // Not empty - Some(this) => { - // alt = Some(GString::from(this.to_string())); - name.push(this.to_string()); - } - // Empty, use resolved address - None => name.push(link.to_string()), + if let Some(value) = regex.get(3) { + alt = Some(GString::from(value.as_str())) }; - // Markup - markup = gformat!( - "{}\n", - markup_escape_text(&uri.to_str()), // use resolved address for href - markup_escape_text(&link), // show original address for title - markup_escape_text(&name.join(" ")), - ); - Some(Self { - // alt, - // date, - // external, - // link, - markup, - // uri, + alt, + date, + is_external, + uri, }) } - - // Getters - /* @TODO - pub fn alt(&self) -> &Option { - &self.alt - } - - pub fn date(&self) -> &Option { - &self.date - } - - pub fn external(&self) -> &bool { - &self.external - } - - pub fn link(&self) -> &GString { - &self.link - } - - pub fn uri(&self) -> &Uri { - &self.uri - }*/ - - pub fn markup(&self) -> &GString { - &self.markup - } }