implement 1-6 level header tags

This commit is contained in:
yggverse 2026-03-08 05:04:50 +02:00
parent 191057cc50
commit 31346d1d63
3 changed files with 82 additions and 22 deletions

View file

@ -37,8 +37,22 @@ impl Markdown {
pub fn build( pub fn build(
(window_action, item_action): (&Rc<WindowAction>, &Rc<ItemAction>), (window_action, item_action): (&Rc<WindowAction>, &Rc<ItemAction>),
base: &Uri, base: &Uri,
gemtext: &str, markdown: &str,
) -> Result<Self, Error> { ) -> Result<Self, Error> {
/// Header tag
fn header(buffer: &TextBuffer, tag: &TextTag, line: &str, pattern: &str) -> Option<String> {
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 // Init default values
let mut title = None; let mut title = None;
@ -98,7 +112,7 @@ impl Markdown {
let is_code_enabled = { let is_code_enabled = {
use ggemtext::line::code::{self}; use ggemtext::line::code::{self};
let mut t: usize = 0; let mut t: usize = 0;
for l in gemtext.lines() { for l in markdown.lines() {
if l.starts_with(code::TAG) { if l.starts_with(code::TAG) {
t += 1; t += 1;
} }
@ -106,8 +120,8 @@ impl Markdown {
t == 0 || t.is_multiple_of(2) t == 0 || t.is_multiple_of(2)
}; };
// Parse gemtext lines // Parse markdown lines
for line in gemtext.lines() { 'l: for line in markdown.lines() {
if is_code_enabled { if is_code_enabled {
use ggemtext::line::Code; use ggemtext::line::Code;
match code { match code {
@ -192,25 +206,27 @@ impl Markdown {
} }
} }
// Is header // Is 1-6 level header
{ for level in 1..=6 {
use ggemtext::line::{Header, header::Level}; if let Some(t) = header(
if let Some(header) = Header::parse(line) { &buffer,
buffer.insert_with_tags( match level {
&mut buffer.end_iter(), 1 => &tag.h1,
&header.value, 2 => &tag.h2,
&[match header.level { 3 => &tag.h3,
Level::H1 => &tag.h1, 4 => &tag.h4,
Level::H2 => &tag.h2, 5 => &tag.h5,
Level::H3 => &tag.h3, 6 => &tag.h6,
}], _ => unreachable!(),
); },
buffer.insert(&mut buffer.end_iter(), NEW_LINE); line,
&H.repeat(level),
) {
// Update document title by tag, if not set before
if title.is_none() { 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 }) Ok(Self { text_view, title })
} else { } else {
Err(Error::Markup( 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 }, 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_DOWNLOAD: &str = "download:";
const LINK_PREFIX_SOURCE: &str = "source:"; const LINK_PREFIX_SOURCE: &str = "source:";
const H: &str = "#";

View file

@ -17,6 +17,9 @@ pub struct Tag {
pub h1: TextTag, pub h1: TextTag,
pub h2: TextTag, pub h2: TextTag,
pub h3: TextTag, pub h3: TextTag,
pub h4: TextTag,
pub h5: TextTag,
pub h6: TextTag,
pub list: TextTag, pub list: TextTag,
pub quote: TextTag, pub quote: TextTag,
pub title: TextTag, pub title: TextTag,
@ -36,6 +39,9 @@ impl Tag {
let h1 = TextTag::h1(); let h1 = TextTag::h1();
let h2 = TextTag::h2(); let h2 = TextTag::h2();
let h3 = TextTag::h3(); let h3 = TextTag::h3();
let h4 = TextTag::h4();
let h5 = TextTag::h5();
let h6 = TextTag::h6();
let list = TextTag::list(); let list = TextTag::list();
let quote = TextTag::quote(); let quote = TextTag::quote();
let title = TextTag::title(); let title = TextTag::title();
@ -47,6 +53,9 @@ impl Tag {
text_tag_table.add(&h1); text_tag_table.add(&h1);
text_tag_table.add(&h2); text_tag_table.add(&h2);
text_tag_table.add(&h3); 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(&title);
text_tag_table.add(&list); text_tag_table.add(&list);
text_tag_table.add(&quote); text_tag_table.add(&quote);
@ -58,6 +67,9 @@ impl Tag {
h1, h1,
h2, h2,
h3, h3,
h4,
h5,
h6,
list, list,
quote, quote,
title, title,

View file

@ -4,6 +4,9 @@ pub trait Header {
fn h1() -> Self; fn h1() -> Self;
fn h2() -> Self; fn h2() -> Self;
fn h3() -> Self; fn h3() -> Self;
fn h4() -> Self;
fn h5() -> Self;
fn h6() -> Self;
} }
impl Header for TextTag { impl Header for TextTag {
@ -34,4 +37,31 @@ impl Header for TextTag {
.wrap_mode(WrapMode::Word) .wrap_mode(WrapMode::Word)
.build() .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()
}
} }