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 57e8416f..2e2c53fe 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 @@ -81,8 +81,8 @@ impl Reader { for line in gemtext.lines() { // Is inline code if let Some(code) = Inline::from(line) { - // Append value to buffer - match syntax.highlight(&code.value, &tag.code.text_tag, None) { + // Try auto-detect code syntax for given `value` + match syntax.highlight(&code.value, None) { Ok(highlight) => { for (syntax_tag, entity) in highlight { // Register new tag @@ -98,6 +98,7 @@ impl Reader { } } Err(_) => { + // Nothing match, append default `Code` tag into the main buffer buffer.insert_with_tags( &mut buffer.end_iter(), &code.value, @@ -149,8 +150,9 @@ impl Reader { None => None, }; - // Insert multiline code into main buffer - match syntax.highlight(&this.value, &tag.code.text_tag, alt) { + // Begin code block construction + // Try auto-detect code syntax for given `value` and `alt` + match syntax.highlight(&this.value, alt) { Ok(highlight) => { for (syntax_tag, entity) in highlight { // Register new tag @@ -166,6 +168,9 @@ impl Reader { } } Err(_) => { + // Try ANSI/SGR highlight (terminal emulation) + + // Nothing match, append default `Code` tag into the main buffer buffer.insert_with_tags( &mut buffer.end_iter(), &this.value, diff --git a/src/app/browser/window/tab/item/page/content/text/gemini/reader/syntax.rs b/src/app/browser/window/tab/item/page/content/text/gemini/reader/syntax.rs index 7a3205ee..8b8e27d1 100644 --- a/src/app/browser/window/tab/item/page/content/text/gemini/reader/syntax.rs +++ b/src/app/browser/window/tab/item/page/content/text/gemini/reader/syntax.rs @@ -1,5 +1,8 @@ pub mod error; +mod tag; + pub use error::Error; +use tag::Tag; use adw::StyleManager; use gtk::{ @@ -50,25 +53,24 @@ impl Syntax { pub fn highlight( &self, source_code: &str, - source_tag: &TextTag, alt: Option<&String>, ) -> Result, Error> { if let Some(value) = alt { if let Some(reference) = self.syntax_set.find_syntax_by_name(value) { - return self.buffer(source_code, source_tag, reference); + return self.buffer(source_code, reference); } if let Some(reference) = self.syntax_set.find_syntax_by_token(value) { - return self.buffer(source_code, source_tag, reference); + return self.buffer(source_code, reference); } if let Some(reference) = self.syntax_set.find_syntax_by_path(value) { - return self.buffer(source_code, source_tag, reference); + return self.buffer(source_code, reference); } } if let Some(reference) = self.syntax_set.find_syntax_by_first_line(source_code) { - return self.buffer(source_code, source_tag, reference); + return self.buffer(source_code, reference); } Err(Error::Parse) @@ -77,7 +79,6 @@ impl Syntax { fn buffer( &self, source: &str, - source_tag: &TextTag, syntax_reference: &SyntaxReference, ) -> Result, Error> { // Init new line buffer @@ -98,16 +99,19 @@ impl Syntax { // Build tags for (style, entity) in result { // Create new tag preset from source - let tag = new_text_tag_from(source_tag); + let tag = Tag::new(); // Tuneup using syntect conversion // tag.set_background_rgba(Some(&color_to_rgba(style.background))); - tag.set_foreground_rgba(Some(&color_to_rgba(style.foreground))); - tag.set_style(font_style_to_style(style.font_style)); - tag.set_underline(font_style_to_underline(style.font_style)); + tag.text_tag + .set_foreground_rgba(Some(&color_to_rgba(style.foreground))); + tag.text_tag + .set_style(font_style_to_style(style.font_style)); + tag.text_tag + .set_underline(font_style_to_underline(style.font_style)); // Append - buffer.push((tag, entity.to_string())); + buffer.push((tag.text_tag, entity.to_string())); } Ok(buffer) } @@ -140,21 +144,3 @@ fn font_style_to_underline(font_style: FontStyle) -> Underline { _ => Underline::None, } } - -fn new_text_tag_from(source_tag: &TextTag) -> TextTag { - let text_tag = TextTag::builder() - .left_margin(source_tag.left_margin()) - .scale(source_tag.scale()) - .wrap_mode(source_tag.wrap_mode()) - .build(); - - if let Some(ref family) = source_tag.family() { - text_tag.set_family(Some(family)); - } - - if let Some(ref foreground_rgba) = source_tag.foreground_rgba() { - text_tag.set_foreground_rgba(Some(foreground_rgba)); - } - - text_tag -} diff --git a/src/app/browser/window/tab/item/page/content/text/gemini/reader/syntax/tag.rs b/src/app/browser/window/tab/item/page/content/text/gemini/reader/syntax/tag.rs new file mode 100644 index 00000000..415f722a --- /dev/null +++ b/src/app/browser/window/tab/item/page/content/text/gemini/reader/syntax/tag.rs @@ -0,0 +1,23 @@ +use gtk::{TextTag, WrapMode}; + +/// Default [TextTag](https://docs.gtk.org/gtk4/class.TextTag.html) preset +/// for syntax highlight buffer +pub struct Tag { + pub text_tag: TextTag, +} + +impl Tag { + // Constructors + + /// Create new `Self` + pub fn new() -> Self { + Self { + text_tag: TextTag::builder() + .family("monospace") // @TODO + .left_margin(28) + .scale(0.8) + .wrap_mode(WrapMode::None) + .build(), + } + } +}