Browse Source

drop pango markup from parser, update api

master
yggverse 2 months ago
parent
commit
66e0a747f1
  1. 159
      src/app/browser/window/tab/item/page/content/text/gemini/reader/parser/link.rs

159
src/app/browser/window/tab/item/page/content/text/gemini/reader/parser/link.rs

@ -1,58 +1,52 @@
use gtk::glib::{ use gtk::glib::{GString, Regex, RegexCompileFlags, RegexMatchFlags, Uri, UriFlags};
gformat, markup_escape_text, GString, Regex, RegexCompileFlags, RegexMatchFlags, Uri, UriFlags,
};
pub struct Link { pub struct Link {
// alt: Option<GString>, // [optional] alternative text pub alt: Option<GString>,
// date: Option<GString>, // [optional] date @TODO store in UnixTime? pub date: Option<GString>, // @TODO https://docs.gtk.org/glib/struct.Date.html
// external: bool, // external link indicator pub is_external: Option<bool>,
// link: GString, // original link, wanted for title tooltip pub uri: Uri,
markup: GString, // pango markup with escaped special chars
// uri: Uri, // parsed link object (currently not in use)
} }
impl Link { impl Link {
// Link structure parser pub fn from(line: &str, to_base: Option<&Uri>) -> Option<Link> {
// line - gemtext subject to parse // Define initial values
// base - Uri object, required for: let mut alt = None;
// 1. relative to absolute address conversion let mut date = None;
// 2. external links indication let mut is_external = None;
// returns new Link struct or None
pub fn from(line: &str, base: &Uri) -> Option<Link> { // Begin line parse
// Init struct members let regex = Regex::split_simple(
// let mut alt: Option<GString> = None;
// let mut date: Option<GString> = None;
let external: bool;
let link: GString;
let markup: GString;
let uri: Uri;
// Parse line
let parsed = Regex::split_simple(
r"^=>\s*([^\s]+)\s*(\d{4}-\d{2}-\d{2})?\s*(.+)?$", r"^=>\s*([^\s]+)\s*(\d{4}-\d{2}-\d{2})?\s*(.+)?$",
line, line,
RegexCompileFlags::DEFAULT, RegexCompileFlags::DEFAULT,
RegexMatchFlags::DEFAULT, RegexMatchFlags::DEFAULT,
); );
// Address // Detect address required to continue
match parsed.get(1) { let unresolved_address = regex.get(1)?;
Some(address) => {
// Define original link value (used in titles or when alt is empty) // Convert address to the valid URI
link = GString::from(address.as_str()); let uri = match to_base {
// Links in document usually relative, make them absolute to base given // Base conversion requested
match Uri::resolve_relative(Some(&base.to_str()), address.as_str(), UriFlags::NONE) Some(base_uri) => {
{ // Convert relative address to absolute
Ok(resolved) => { match Uri::resolve_relative(
// Make URI parsed as always valid (no idea why does lib operate strings, not objects) Some(&base_uri.to_str()),
match Uri::parse(&resolved, UriFlags::NONE) { unresolved_address.as_str(),
Ok(object) => { UriFlags::NONE,
// Set external status ) {
external = Ok(resolved_str) => {
object.host() != base.host() || object.port() != base.port(); // Try convert string to the valid URI
match Uri::parse(&resolved_str, UriFlags::NONE) {
// Set struct URI Ok(resolved_uri) => {
uri = object; // Change external status
is_external = Some(
resolved_uri.host() != base_uri.host()
|| resolved_uri.port() != base_uri.port(),
);
// Result
resolved_uri
} }
Err(_) => return None, Err(_) => return None,
} }
@ -60,74 +54,31 @@ impl Link {
Err(_) => return None, Err(_) => return None,
} }
} }
None => return None, // Base resolve not requested
} None => {
// Just try convert address to valid URI
// Create link name based on external status, date and alt values match Uri::parse(&unresolved_address, UriFlags::NONE) {
let mut name = Vec::new(); Ok(unresolved_uri) => unresolved_uri,
Err(_) => return None,
if external { }
name.push("⇖".to_string()); }
} };
// Date // Date
if let Some(this) = parsed.get(2) { if let Some(value) = regex.get(2) {
// date = Some(GString::from(this.to_string())); date = Some(GString::from(value.as_str()))
name.push(this.to_string());
} }
// Alt // Alt
match parsed.get(3) { if let Some(value) = regex.get(3) {
// Not empty alt = Some(GString::from(value.as_str()))
Some(this) => {
// alt = Some(GString::from(this.to_string()));
name.push(this.to_string());
}
// Empty, use resolved address
None => name.push(link.to_string()),
}; };
// Markup
markup = gformat!(
"<a href=\"{}\" title=\"{}\"><span underline=\"none\">{}</span></a>\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 { Some(Self {
// alt, alt,
// date, date,
// external, is_external,
// link, uri,
markup,
// uri,
}) })
} }
// Getters
/* @TODO
pub fn alt(&self) -> &Option<GString> {
&self.alt
}
pub fn date(&self) -> &Option<GString> {
&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
}
} }

Loading…
Cancel
Save