diff --git a/src/app/browser/window/tab/item/page/content/text/gemini/reader.rs b/src/app/browser/window/tab/item/page/content/text/gemini/reader.rs index 7d107daf..ed2ed337 100644 --- a/src/app/browser/window/tab/item/page/content/text/gemini/reader.rs +++ b/src/app/browser/window/tab/item/page/content/text/gemini/reader.rs @@ -3,6 +3,8 @@ mod widget; use parser::header::Header; use parser::link::Link; +use parser::list::List; +use parser::quote::Quote; use widget::Widget; use adw::StyleManager; @@ -10,6 +12,7 @@ use gtk::{ gdk::{BUTTON_MIDDLE, BUTTON_PRIMARY}, gio::SimpleAction, glib::{GString, TimeZone, Uri}, + pango::Style, prelude::{ActionExt, TextBufferExt, TextBufferExtManual, TextViewExt, ToVariant, WidgetExt}, EventControllerMotion, GestureClick, TextBuffer, TextTag, TextView, TextWindowType, WrapMode, }; @@ -130,6 +133,42 @@ impl Reader { continue; } + // Is list + if let Some(list) = List::from(line) { + // Build tag from level parsed + let tag = TextTag::builder().wrap_mode(gtk::WrapMode::Word).build(); + + // Register tag in buffer + buffer.tag_table().add(&tag); + + // Append value to buffer + buffer.insert(&mut buffer.end_iter(), " • "); + buffer.insert_with_tags(&mut buffer.end_iter(), list.value.as_str(), &[&tag]); + buffer.insert(&mut buffer.end_iter(), "\n"); + + // Skip other actions for this line + continue; + } + + // Is quote + if let Some(quote) = Quote::from(line) { + // Build tag from level parsed + let tag = TextTag::builder() + .style(Style::Italic) + .wrap_mode(gtk::WrapMode::Word) + .build(); + + // Register tag in buffer + buffer.tag_table().add(&tag); + + // Append value to buffer + buffer.insert_with_tags(&mut buffer.end_iter(), quote.value.as_str(), &[&tag]); + buffer.insert(&mut buffer.end_iter(), "\n"); + + // Skip other actions for this line + continue; + } + // Nothing match custom tags above, // just append plain text covered in empty tag (to handle controller events properly) let tag = TextTag::builder().wrap_mode(WrapMode::Word).build(); diff --git a/src/app/browser/window/tab/item/page/content/text/gemini/reader/parser.rs b/src/app/browser/window/tab/item/page/content/text/gemini/reader/parser.rs index d3477c7b..5ac64a79 100644 --- a/src/app/browser/window/tab/item/page/content/text/gemini/reader/parser.rs +++ b/src/app/browser/window/tab/item/page/content/text/gemini/reader/parser.rs @@ -1,2 +1,4 @@ pub mod header; pub mod link; +pub mod list; +pub mod quote; diff --git a/src/app/browser/window/tab/item/page/content/text/gemini/reader/parser/header.rs b/src/app/browser/window/tab/item/page/content/text/gemini/reader/parser/header.rs index bf0a4e6c..24dc2482 100644 --- a/src/app/browser/window/tab/item/page/content/text/gemini/reader/parser/header.rs +++ b/src/app/browser/window/tab/item/page/content/text/gemini/reader/parser/header.rs @@ -39,7 +39,7 @@ impl Header { } // Result - Some(Header { + Some(Self { level, value: GString::from(value.as_str()), }) diff --git a/src/app/browser/window/tab/item/page/content/text/gemini/reader/parser/list.rs b/src/app/browser/window/tab/item/page/content/text/gemini/reader/parser/list.rs new file mode 100644 index 00000000..f2598e5d --- /dev/null +++ b/src/app/browser/window/tab/item/page/content/text/gemini/reader/parser/list.rs @@ -0,0 +1,29 @@ +use gtk::glib::{GString, Regex, RegexCompileFlags, RegexMatchFlags}; + +pub struct List { + pub value: GString, +} + +impl List { + pub fn from(line: &str) -> Option { + // Parse line + let regex = Regex::split_simple( + r"^\*\s*(.+)$", + line, + RegexCompileFlags::DEFAULT, + RegexMatchFlags::DEFAULT, + ); + + // Detect value + let value = regex.get(1)?; + + if value.trim().is_empty() { + return None; + } + + // Result + Some(Self { + value: GString::from(value.as_str()), + }) + } +} diff --git a/src/app/browser/window/tab/item/page/content/text/gemini/reader/parser/quote.rs b/src/app/browser/window/tab/item/page/content/text/gemini/reader/parser/quote.rs new file mode 100644 index 00000000..20d69b6c --- /dev/null +++ b/src/app/browser/window/tab/item/page/content/text/gemini/reader/parser/quote.rs @@ -0,0 +1,29 @@ +use gtk::glib::{GString, Regex, RegexCompileFlags, RegexMatchFlags}; + +pub struct Quote { + pub value: GString, +} + +impl Quote { + pub fn from(line: &str) -> Option { + // Parse line + let regex = Regex::split_simple( + r"^>\s*(.+)$", + line, + RegexCompileFlags::DEFAULT, + RegexMatchFlags::DEFAULT, + ); + + // Detect value + let value = regex.get(1)?; + + if value.trim().is_empty() { + return None; + } + + // Result + Some(Self { + value: GString::from(value.as_str()), + }) + } +}