mirror of
https://github.com/YGGverse/Yoda.git
synced 2026-03-31 08:35:28 +00:00
add header tags renderer
This commit is contained in:
parent
e653675fa1
commit
c732964494
2 changed files with 59 additions and 27 deletions
|
|
@ -108,8 +108,10 @@ impl Markdown {
|
||||||
t == 0 || t.is_multiple_of(2)
|
t == 0 || t.is_multiple_of(2)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Parse in-line markdown tags
|
// Render markdown tags
|
||||||
// * keep order!
|
// * keep in order!
|
||||||
|
|
||||||
|
tag::header(&buffer, &tag);
|
||||||
|
|
||||||
reference::image_link(&buffer, &tag, base, &link_color.0, &mut links);
|
reference::image_link(&buffer, &tag, base, &link_color.0, &mut links);
|
||||||
reference::image(&buffer, &tag, base, &link_color.0, &mut links);
|
reference::image(&buffer, &tag, base, &link_color.0, &mut links);
|
||||||
|
|
@ -201,30 +203,6 @@ impl Markdown {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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(t);
|
|
||||||
}
|
|
||||||
continue 'l;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Is list
|
// Is list
|
||||||
|
|
||||||
if let Some(value) = ggemtext::line::list::Gemtext::as_value(line) {
|
if let Some(value) = ggemtext::line::list::Gemtext::as_value(line) {
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,15 @@ mod plain;
|
||||||
mod quote;
|
mod quote;
|
||||||
mod title;
|
mod title;
|
||||||
|
|
||||||
use gtk::{TextTag, TextTagTable};
|
use gtk::{
|
||||||
|
TextBuffer, TextTag, TextTagTable,
|
||||||
|
prelude::{TextBufferExt, TextBufferExtManual},
|
||||||
|
};
|
||||||
use header::Header;
|
use header::Header;
|
||||||
use list::List;
|
use list::List;
|
||||||
use plain::Plain;
|
use plain::Plain;
|
||||||
use quote::Quote;
|
use quote::Quote;
|
||||||
|
use regex::Regex;
|
||||||
use title::Title;
|
use title::Title;
|
||||||
|
|
||||||
pub struct Tag {
|
pub struct Tag {
|
||||||
|
|
@ -77,3 +81,53 @@ impl Tag {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Headers `#`, `##`, etc.
|
||||||
|
|
||||||
|
const REGEX_HEADER: &str = r"(?m)^(?P<level>#{1,6})\s+(?P<title>.*)$";
|
||||||
|
|
||||||
|
/// Apply header `Tag` to given `TextBuffer`
|
||||||
|
pub fn header(buffer: &TextBuffer, tag: &Tag) {
|
||||||
|
let (start, end) = buffer.bounds();
|
||||||
|
let full_content = buffer.text(&start, &end, true).to_string();
|
||||||
|
|
||||||
|
let matches: Vec<_> = Regex::new(REGEX_HEADER)
|
||||||
|
.unwrap()
|
||||||
|
.captures_iter(&full_content)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
for cap in matches.into_iter().rev() {
|
||||||
|
let full_match = cap.get(0).unwrap();
|
||||||
|
|
||||||
|
let start_char_offset = full_content[..full_match.start()].chars().count() as i32;
|
||||||
|
let end_char_offset = full_content[..full_match.end()].chars().count() as i32;
|
||||||
|
|
||||||
|
let mut start_iter = buffer.iter_at_offset(start_char_offset);
|
||||||
|
let mut end_iter = buffer.iter_at_offset(end_char_offset);
|
||||||
|
|
||||||
|
buffer.delete(&mut start_iter, &mut end_iter);
|
||||||
|
|
||||||
|
match cap["level"].chars().count() {
|
||||||
|
1 => buffer.insert_with_tags(&mut start_iter, &cap["title"], &[&tag.h1]),
|
||||||
|
2 => buffer.insert_with_tags(&mut start_iter, &cap["title"], &[&tag.h2]),
|
||||||
|
3 => buffer.insert_with_tags(&mut start_iter, &cap["title"], &[&tag.h3]),
|
||||||
|
4 => buffer.insert_with_tags(&mut start_iter, &cap["title"], &[&tag.h4]),
|
||||||
|
5 => buffer.insert_with_tags(&mut start_iter, &cap["title"], &[&tag.h5]),
|
||||||
|
6 => buffer.insert_with_tags(&mut start_iter, &cap["title"], &[&tag.h6]),
|
||||||
|
_ => buffer.insert_with_tags(&mut start_iter, &cap["title"], &[]),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_regex_header() {
|
||||||
|
let cap: Vec<_> = Regex::new(REGEX_HEADER)
|
||||||
|
.unwrap()
|
||||||
|
.captures_iter(r"## Title ")
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let first = cap.get(0).unwrap();
|
||||||
|
assert_eq!(&first[0], "## Title ");
|
||||||
|
assert_eq!(&first["level"], "##");
|
||||||
|
assert_eq!(&first["title"], "Title ");
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue