mirror of
https://github.com/YGGverse/ggemtext.git
synced 2026-03-31 17:15:33 +00:00
reorganize header component
This commit is contained in:
parent
c29f1ba529
commit
3e16995e00
3 changed files with 105 additions and 68 deletions
|
|
@ -1,15 +1,8 @@
|
||||||
/// [Header](https://geminiprotocol.net/docs/gemtext-specification.gmi#heading-lines) tag
|
pub mod gemtext;
|
||||||
/// * store as entire static chars array
|
pub mod level;
|
||||||
pub const TAG_H1: &str = "#";
|
|
||||||
pub const TAG_H2: &str = "##";
|
|
||||||
pub const TAG_H3: &str = "###";
|
|
||||||
|
|
||||||
/// [Header](https://geminiprotocol.net/docs/gemtext-specification.gmi#heading-lines) type holder
|
pub use gemtext::Gemtext;
|
||||||
pub enum Level {
|
pub use level::Level;
|
||||||
H1,
|
|
||||||
H2,
|
|
||||||
H3,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// [Header](https://geminiprotocol.net/docs/gemtext-specification.gmi#heading-lines) entity holder
|
/// [Header](https://geminiprotocol.net/docs/gemtext-specification.gmi#heading-lines) entity holder
|
||||||
pub struct Header {
|
pub struct Header {
|
||||||
|
|
@ -22,10 +15,25 @@ impl Header {
|
||||||
|
|
||||||
/// Parse `Self` from line string
|
/// Parse `Self` from line string
|
||||||
pub fn parse(line: &str) -> Option<Self> {
|
pub fn parse(line: &str) -> Option<Self> {
|
||||||
Some(Self {
|
if let Some(value) = line.as_h1_value() {
|
||||||
level: line.to_level()?,
|
return Some(Self {
|
||||||
value: line.as_value()?.to_string(),
|
level: Level::H1,
|
||||||
})
|
value: value.to_string(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if let Some(value) = line.as_h2_value() {
|
||||||
|
return Some(Self {
|
||||||
|
level: Level::H2,
|
||||||
|
value: value.to_string(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if let Some(value) = line.as_h3_value() {
|
||||||
|
return Some(Self {
|
||||||
|
level: Level::H3,
|
||||||
|
value: value.to_string(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
// Converters
|
// Converters
|
||||||
|
|
@ -35,56 +43,3 @@ impl Header {
|
||||||
self.value.to_source(&self.level)
|
self.value.to_source(&self.level)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Gemtext {
|
|
||||||
/// Get [Gemtext](https://geminiprotocol.net/docs/gemtext-specification.gmi) value for `Self`
|
|
||||||
fn as_value(&self) -> Option<&Self>;
|
|
||||||
/// Convert `Self` to `Level`
|
|
||||||
fn to_level(&self) -> Option<Level>;
|
|
||||||
/// Convert `Self` to [Gemtext](https://geminiprotocol.net/docs/gemtext-specification.gmi) line
|
|
||||||
fn to_source(&self, level: &Level) -> String;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Gemtext for str {
|
|
||||||
fn as_value(&self) -> Option<&str> {
|
|
||||||
if let Some(h3) = self.strip_prefix(TAG_H3) {
|
|
||||||
if h3.trim_start().starts_with(TAG_H1) {
|
|
||||||
return None; // H4+
|
|
||||||
}
|
|
||||||
return Some(h3.trim());
|
|
||||||
}
|
|
||||||
if let Some(h2) = self.strip_prefix(TAG_H2) {
|
|
||||||
return Some(h2.trim());
|
|
||||||
}
|
|
||||||
if let Some(h1) = self.strip_prefix(TAG_H1) {
|
|
||||||
return Some(h1.trim());
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
fn to_level(&self) -> Option<Level> {
|
|
||||||
if let Some(h3) = self.strip_prefix(TAG_H3) {
|
|
||||||
if h3.trim_start().starts_with(TAG_H1) {
|
|
||||||
return None; // H4+
|
|
||||||
}
|
|
||||||
return Some(Level::H3);
|
|
||||||
}
|
|
||||||
if self.starts_with(TAG_H2) {
|
|
||||||
return Some(Level::H2);
|
|
||||||
}
|
|
||||||
if self.starts_with(TAG_H1) {
|
|
||||||
return Some(Level::H1);
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
fn to_source(&self, level: &Level) -> String {
|
|
||||||
format!(
|
|
||||||
"{} {}",
|
|
||||||
match level {
|
|
||||||
Level::H1 => TAG_H1,
|
|
||||||
Level::H2 => TAG_H2,
|
|
||||||
Level::H3 => TAG_H3,
|
|
||||||
},
|
|
||||||
self.trim()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
66
src/line/header/gemtext.rs
Normal file
66
src/line/header/gemtext.rs
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
use super::Level;
|
||||||
|
|
||||||
|
pub trait Gemtext {
|
||||||
|
/// Get [Gemtext](https://geminiprotocol.net/docs/gemtext-specification.gmi) value for `Self`
|
||||||
|
fn as_value(&self) -> Option<&str>;
|
||||||
|
/// Get parsed H1 header value for `Self`
|
||||||
|
fn as_h1_value(&self) -> Option<&str>;
|
||||||
|
/// Get parsed H2 header value `Self`
|
||||||
|
fn as_h2_value(&self) -> Option<&str>;
|
||||||
|
/// Get parsed H3 header value `Self`
|
||||||
|
fn as_h3_value(&self) -> Option<&str>;
|
||||||
|
/// Get parsed header value `Self` match `Level`
|
||||||
|
fn as_value_match_level(&self, level: Level) -> Option<&str>;
|
||||||
|
/// Convert `Self` to `Level`
|
||||||
|
fn to_level(&self) -> Option<Level>;
|
||||||
|
/// Convert `Self` to [Gemtext](https://geminiprotocol.net/docs/gemtext-specification.gmi) line
|
||||||
|
fn to_source(&self, level: &Level) -> String;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Gemtext for str {
|
||||||
|
fn as_value(&self) -> Option<&str> {
|
||||||
|
if let Some(value) = self.as_h1_value() {
|
||||||
|
return Some(value);
|
||||||
|
}
|
||||||
|
if let Some(value) = self.as_h2_value() {
|
||||||
|
return Some(value);
|
||||||
|
}
|
||||||
|
if let Some(value) = self.as_h3_value() {
|
||||||
|
return Some(value);
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
fn as_h1_value(&self) -> Option<&str> {
|
||||||
|
self.as_value_match_level(Level::H1)
|
||||||
|
}
|
||||||
|
fn as_h2_value(&self) -> Option<&str> {
|
||||||
|
self.as_value_match_level(Level::H2)
|
||||||
|
}
|
||||||
|
fn as_h3_value(&self) -> Option<&str> {
|
||||||
|
self.as_value_match_level(Level::H3)
|
||||||
|
}
|
||||||
|
fn as_value_match_level(&self, level: Level) -> Option<&str> {
|
||||||
|
if let Some(value) = self.strip_prefix(level.as_tag()) {
|
||||||
|
if value.trim_start().starts_with(Level::H1.as_tag()) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
return Some(value.trim());
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
fn to_level(&self) -> Option<Level> {
|
||||||
|
if self.as_h1_value().is_some() {
|
||||||
|
return Some(Level::H1);
|
||||||
|
}
|
||||||
|
if self.as_h2_value().is_some() {
|
||||||
|
return Some(Level::H2);
|
||||||
|
}
|
||||||
|
if self.as_h3_value().is_some() {
|
||||||
|
return Some(Level::H3);
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
fn to_source(&self, level: &Level) -> String {
|
||||||
|
format!("{} {}", level.as_tag(), self.trim())
|
||||||
|
}
|
||||||
|
}
|
||||||
16
src/line/header/level.rs
Normal file
16
src/line/header/level.rs
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
/// [Header](https://geminiprotocol.net/docs/gemtext-specification.gmi#heading-lines) type holder
|
||||||
|
pub enum Level {
|
||||||
|
H1,
|
||||||
|
H2,
|
||||||
|
H3,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Level {
|
||||||
|
pub fn as_tag(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
Level::H1 => "#",
|
||||||
|
Level::H2 => "##",
|
||||||
|
Level::H3 => "###",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue