mirror of https://github.com/YGGverse/Yoda.git
yggverse
1 month ago
9 changed files with 9 additions and 300 deletions
@ -1,25 +0,0 @@
@@ -1,25 +0,0 @@
|
||||
pub mod inline; |
||||
pub mod multiline; |
||||
|
||||
use inline::Inline; |
||||
use multiline::Multiline; |
||||
|
||||
pub struct Code { |
||||
// nothing yet..
|
||||
} |
||||
|
||||
impl Code { |
||||
// Inline
|
||||
pub fn inline_from(line: &str) -> Option<Inline> { |
||||
Inline::from(line) |
||||
} |
||||
|
||||
// Multiline
|
||||
pub fn multiline_begin_from(line: &str) -> Option<Multiline> { |
||||
Multiline::begin_from(line) |
||||
} |
||||
|
||||
pub fn multiline_continue_from(this: &mut Multiline, line: &str) { |
||||
Multiline::continue_from(this, line) |
||||
} |
||||
} |
@ -1,29 +0,0 @@
@@ -1,29 +0,0 @@
|
||||
use gtk::glib::{GString, Regex, RegexCompileFlags, RegexMatchFlags}; |
||||
|
||||
pub struct Inline { |
||||
pub value: GString, |
||||
} |
||||
|
||||
impl Inline { |
||||
pub fn from(line: &str) -> Option<Self> { |
||||
// Parse line
|
||||
let regex = Regex::split_simple( |
||||
r"^`{3}([^`]*)`{3}$", |
||||
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()), |
||||
}) |
||||
} |
||||
} |
@ -1,46 +0,0 @@
@@ -1,46 +0,0 @@
|
||||
use gtk::glib::GString; |
||||
|
||||
pub struct Multiline { |
||||
pub alt: Option<GString>, |
||||
pub buffer: Vec<GString>, |
||||
pub completed: bool, |
||||
} |
||||
|
||||
impl Multiline { |
||||
// Search in line for tag open,
|
||||
// return Self constructed on success or None
|
||||
pub fn begin_from(line: &str) -> Option<Self> { |
||||
if line.starts_with("```") { |
||||
let alt = line.trim_start_matches("```"); |
||||
|
||||
return Some(Self { |
||||
alt: match alt.trim().is_empty() { |
||||
true => None, |
||||
false => Some(GString::from(alt)), |
||||
}, |
||||
buffer: Vec::new(), |
||||
completed: false, |
||||
}); |
||||
} |
||||
|
||||
None |
||||
} |
||||
|
||||
// Continue preformatted buffer from line,
|
||||
// set `completed` as True on close tag found
|
||||
pub fn continue_from(&mut self, line: &str) { |
||||
// Make sure buffer not completed yet
|
||||
if self.completed { |
||||
panic!("Could not continue as completed") // @TODO handle
|
||||
} |
||||
|
||||
// Line contain close tag
|
||||
if line.ends_with("```") { |
||||
self.completed = true; |
||||
} |
||||
|
||||
// Append data to the buffer, trim close tag on exists
|
||||
self.buffer |
||||
.push(GString::from(line.trim_end_matches("```"))); |
||||
} |
||||
} |
@ -1,47 +0,0 @@
@@ -1,47 +0,0 @@
|
||||
use gtk::glib::{GString, Regex, RegexCompileFlags, RegexMatchFlags}; |
||||
|
||||
pub enum Level { |
||||
H1, |
||||
H2, |
||||
H3, |
||||
} |
||||
|
||||
pub struct Header { |
||||
pub value: GString, |
||||
pub level: Level, |
||||
} |
||||
|
||||
impl Header { |
||||
pub fn from(line: &str) -> Option<Self> { |
||||
// Parse line
|
||||
let regex = Regex::split_simple( |
||||
r"^(#{1,3})\s*(.+)$", |
||||
line, |
||||
RegexCompileFlags::DEFAULT, |
||||
RegexMatchFlags::DEFAULT, |
||||
); |
||||
|
||||
// Detect header level
|
||||
let level = regex.get(1)?; |
||||
|
||||
let level = match level.len() { |
||||
1 => Level::H1, |
||||
2 => Level::H2, |
||||
3 => Level::H3, |
||||
_ => return None, |
||||
}; |
||||
|
||||
// Detect header value
|
||||
let value = regex.get(2)?; |
||||
|
||||
if value.trim().is_empty() { |
||||
return None; |
||||
} |
||||
|
||||
// Result
|
||||
Some(Self { |
||||
level, |
||||
value: GString::from(value.as_str()), |
||||
}) |
||||
} |
||||
} |
@ -1,89 +0,0 @@
@@ -1,89 +0,0 @@
|
||||
use gtk::glib::{ |
||||
DateTime, GString, Regex, RegexCompileFlags, RegexMatchFlags, TimeZone, Uri, UriFlags, |
||||
}; |
||||
|
||||
pub struct Link { |
||||
pub alt: Option<GString>, // [optional] alternative link description
|
||||
pub is_external: Option<bool>, // [optional] external link indication, on base option provided
|
||||
pub timestamp: Option<DateTime>, // [optional] valid link DateTime object
|
||||
pub uri: Uri, // [required] valid link URI object
|
||||
} |
||||
|
||||
impl Link { |
||||
pub fn from(line: &str, base: Option<&Uri>, timezone: Option<&TimeZone>) -> Option<Self> { |
||||
// Define initial values
|
||||
let mut alt = None; |
||||
let mut timestamp = 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, |
||||
); |
||||
|
||||
// Detect address required to continue
|
||||
let unresolved_address = regex.get(1)?; |
||||
|
||||
// Convert address to the valid URI
|
||||
let uri = match 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.scheme() != base_uri.scheme()); |
||||
|
||||
// Result
|
||||
resolved_uri |
||||
} |
||||
Err(_) => return None, |
||||
} |
||||
} |
||||
Err(_) => return None, |
||||
} |
||||
} |
||||
// 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, |
||||
} |
||||
} |
||||
}; |
||||
|
||||
// Timestamp
|
||||
if let Some(date) = regex.get(2) { |
||||
// @TODO even possible, but simpler to work with `DateTime` API
|
||||
// await for new features in `Date` as better in Gemini context
|
||||
// https://docs.gtk.org/glib/struct.Date.html
|
||||
timestamp = match DateTime::from_iso8601(&format!("{date}T00:00:00"), timezone) { |
||||
Ok(value) => Some(value), |
||||
Err(_) => None, |
||||
} |
||||
} |
||||
|
||||
// Alt
|
||||
if let Some(value) = regex.get(3) { |
||||
alt = Some(GString::from(value.as_str())) |
||||
}; |
||||
|
||||
Some(Self { |
||||
alt, |
||||
is_external, |
||||
timestamp, |
||||
uri, |
||||
}) |
||||
} |
||||
} |
@ -1,29 +0,0 @@
@@ -1,29 +0,0 @@
|
||||
use gtk::glib::{GString, Regex, RegexCompileFlags, RegexMatchFlags}; |
||||
|
||||
pub struct List { |
||||
pub value: GString, |
||||
} |
||||
|
||||
impl List { |
||||
pub fn from(line: &str) -> Option<Self> { |
||||
// 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()), |
||||
}) |
||||
} |
||||
} |
@ -1,29 +0,0 @@
@@ -1,29 +0,0 @@
|
||||
use gtk::glib::{GString, Regex, RegexCompileFlags, RegexMatchFlags}; |
||||
|
||||
pub struct Quote { |
||||
pub value: GString, |
||||
} |
||||
|
||||
impl Quote { |
||||
pub fn from(line: &str) -> Option<Self> { |
||||
// 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()), |
||||
}) |
||||
} |
||||
} |
Loading…
Reference in new issue