From 31346d1d63da8b875318995a2ac85a1105065d29 Mon Sep 17 00:00:00 2001 From: yggverse Date: Sun, 8 Mar 2026 05:04:50 +0200 Subject: [PATCH] implement 1-6 level header tags --- .../tab/item/page/content/text/markdown.rs | 62 ++++++++++++------- .../item/page/content/text/markdown/tag.rs | 12 ++++ .../page/content/text/markdown/tag/header.rs | 30 +++++++++ 3 files changed, 82 insertions(+), 22 deletions(-) diff --git a/src/app/browser/window/tab/item/page/content/text/markdown.rs b/src/app/browser/window/tab/item/page/content/text/markdown.rs index 30c57661..0435dd64 100644 --- a/src/app/browser/window/tab/item/page/content/text/markdown.rs +++ b/src/app/browser/window/tab/item/page/content/text/markdown.rs @@ -37,8 +37,22 @@ impl Markdown { pub fn build( (window_action, item_action): (&Rc, &Rc), base: &Uri, - gemtext: &str, + markdown: &str, ) -> Result { + /// Header tag + fn header(buffer: &TextBuffer, tag: &TextTag, line: &str, pattern: &str) -> Option { + if let Some(h) = line.trim_start().strip_prefix(pattern) + && !h.starts_with(pattern) + { + let header = h.trim(); + buffer.insert_with_tags(&mut buffer.end_iter(), header, &[tag]); + buffer.insert(&mut buffer.end_iter(), NEW_LINE); + Some(header.into()) + } else { + None + } + } + // Init default values let mut title = None; @@ -98,7 +112,7 @@ impl Markdown { let is_code_enabled = { use ggemtext::line::code::{self}; let mut t: usize = 0; - for l in gemtext.lines() { + for l in markdown.lines() { if l.starts_with(code::TAG) { t += 1; } @@ -106,8 +120,8 @@ impl Markdown { t == 0 || t.is_multiple_of(2) }; - // Parse gemtext lines - for line in gemtext.lines() { + // Parse markdown lines + 'l: for line in markdown.lines() { if is_code_enabled { use ggemtext::line::Code; match code { @@ -192,25 +206,27 @@ impl Markdown { } } - // Is header - { - use ggemtext::line::{Header, header::Level}; - if let Some(header) = Header::parse(line) { - buffer.insert_with_tags( - &mut buffer.end_iter(), - &header.value, - &[match header.level { - Level::H1 => &tag.h1, - Level::H2 => &tag.h2, - Level::H3 => &tag.h3, - }], - ); - buffer.insert(&mut buffer.end_iter(), NEW_LINE); - + // Is 1-6 level header + for level in 1..=6 { + if let Some(t) = header( + &buffer, + match level { + 1 => &tag.h1, + 2 => &tag.h2, + 3 => &tag.h3, + 4 => &tag.h4, + 5 => &tag.h5, + 6 => &tag.h6, + _ => unreachable!(), + }, + line, + &H.repeat(level), + ) { + // Update document title by tag, if not set before if title.is_none() { - title = Some(header.value.clone()); + title = Some(t); } - continue; + continue 'l; } } @@ -521,7 +537,7 @@ impl Markdown { Ok(Self { text_view, title }) } else { Err(Error::Markup( - "Invalid multiline markup! Gemtext format partially ignored.".to_string(), + "Invalid multiline markup! Markdown format partially ignored.".to_string(), Self { text_view, title }, )) } @@ -582,3 +598,5 @@ fn link_prefix(request: String, prefix: &str) -> String { const LINK_PREFIX_DOWNLOAD: &str = "download:"; const LINK_PREFIX_SOURCE: &str = "source:"; + +const H: &str = "#"; diff --git a/src/app/browser/window/tab/item/page/content/text/markdown/tag.rs b/src/app/browser/window/tab/item/page/content/text/markdown/tag.rs index f917b5f7..1ff62227 100644 --- a/src/app/browser/window/tab/item/page/content/text/markdown/tag.rs +++ b/src/app/browser/window/tab/item/page/content/text/markdown/tag.rs @@ -17,6 +17,9 @@ pub struct Tag { pub h1: TextTag, pub h2: TextTag, pub h3: TextTag, + pub h4: TextTag, + pub h5: TextTag, + pub h6: TextTag, pub list: TextTag, pub quote: TextTag, pub title: TextTag, @@ -36,6 +39,9 @@ impl Tag { let h1 = TextTag::h1(); let h2 = TextTag::h2(); let h3 = TextTag::h3(); + let h4 = TextTag::h4(); + let h5 = TextTag::h5(); + let h6 = TextTag::h6(); let list = TextTag::list(); let quote = TextTag::quote(); let title = TextTag::title(); @@ -47,6 +53,9 @@ impl Tag { text_tag_table.add(&h1); text_tag_table.add(&h2); text_tag_table.add(&h3); + text_tag_table.add(&h4); + text_tag_table.add(&h5); + text_tag_table.add(&h6); text_tag_table.add(&title); text_tag_table.add(&list); text_tag_table.add("e); @@ -58,6 +67,9 @@ impl Tag { h1, h2, h3, + h4, + h5, + h6, list, quote, title, diff --git a/src/app/browser/window/tab/item/page/content/text/markdown/tag/header.rs b/src/app/browser/window/tab/item/page/content/text/markdown/tag/header.rs index 8f4c992b..2a376692 100644 --- a/src/app/browser/window/tab/item/page/content/text/markdown/tag/header.rs +++ b/src/app/browser/window/tab/item/page/content/text/markdown/tag/header.rs @@ -4,6 +4,9 @@ pub trait Header { fn h1() -> Self; fn h2() -> Self; fn h3() -> Self; + fn h4() -> Self; + fn h5() -> Self; + fn h6() -> Self; } impl Header for TextTag { @@ -34,4 +37,31 @@ impl Header for TextTag { .wrap_mode(WrapMode::Word) .build() } + fn h4() -> Self { + TextTag::builder() + .foreground("#c88800") // @TODO optional + .scale(1.1) + .sentence(true) + .weight(400) + .wrap_mode(WrapMode::Word) + .build() + } + fn h5() -> Self { + TextTag::builder() + .foreground("#c88800") // @TODO optional + .scale(1.0) + .sentence(true) + .weight(400) + .wrap_mode(WrapMode::Word) + .build() + } + fn h6() -> Self { + TextTag::builder() + .foreground("#c88800") // @TODO optional + .scale(1.0) + .sentence(true) + .weight(300) + .wrap_mode(WrapMode::Word) + .build() + } }