Skip to content

Commit

Permalink
fix(ast): parse preformatted gemtext as preformatted content
Browse files Browse the repository at this point in the history
  • Loading branch information
Fuwn committed Jun 19, 2024
1 parent 15c4937 commit fedb341
Show file tree
Hide file tree
Showing 9 changed files with 78 additions and 182 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[package]
name = "germ"
version = "0.4.1"
version = "0.4.2"
authors = ["Fuwn <[email protected]>"]
edition = "2021"
description = "The Ultimate Gemini Toolkit."
Expand All @@ -23,6 +23,7 @@ macros = ["ast", "convert"]
meta = []
request = ["rustls", "url", "anyhow", "tokio", "tokio-rustls"]
quick = []
example-gemtext = []

[dependencies]
anyhow = { version = "1.0.70", optional = true } # `Result`
Expand Down
31 changes: 1 addition & 30 deletions examples/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,38 +19,9 @@
//! This example demonstrates Germ's capabilities for parsing Gemtext into an
//! abstract syntax tree.
const EXAMPLE_GEMTEXT: &str = r#"```This is alt-text
Here goes the pre-formatted text.
This continues the pre-formatted text on a new line after a blank line.
```
# This is a heading
This is some text.
This is more text after a blank line.
* This is a single list item.
* This is the next list item.
* This is a new list.
* This is the next item on the new list.
## This is a sub-heading
> This is a blockquote.
### This is a sub-sub-heading.
=> gemini://gem.rest/ This is a link to GemRest
=> /somewhere
That was a link without text."#;

fn main() {
// Parse `EXAMPLE_GEMTEXT` into an abstract syntax tree
let ast = germ::ast::Ast::from_string(EXAMPLE_GEMTEXT);
let ast = germ::ast::Ast::from_string(germ::EXAMPLE_GEMTEXT);
// Get the nodes of the abstract syntax tree
let ast_nodes = ast.inner();

Expand Down
31 changes: 1 addition & 30 deletions examples/ast_to_gemtext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,38 +19,9 @@
//! This example converts Gemtext into an abstract syntax tree and then back
//! into Gemtext, demonstrating both Germ's parsing and generation capabilities.
const EXAMPLE_GEMTEXT: &str = r#"```This is alt-text
Here goes the pre-formatted text.
This continues the pre-formatted text on a new line after a blank line.
```
# This is a heading
This is some text.
This is more text after a blank line.
* This is a single list item.
* This is the next list item.
* This is a new list.
* This is the next item on the new list.
## This is a sub-heading
> This is a blockquote.
### This is a sub-sub-heading.
=> gemini://gem.rest/ This is a link to GemRest
=> /somewhere
That was a link without text."#;

fn main() {
// Parse `EXAMPLE_GEMTEXT` into an abstract syntax tree
let ast = germ::ast::Ast::from_string(EXAMPLE_GEMTEXT);
let ast = germ::ast::Ast::from_string(germ::EXAMPLE_GEMTEXT);
// Convert the abstract syntax tree back to Gemtext
let gemtext = ast.to_gemtext();

Expand Down
35 changes: 4 additions & 31 deletions examples/html.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,39 +19,12 @@
//! This example demonstrates Germ's capabilities for converting Gemtext to
//! HTML.
const EXAMPLE_GEMTEXT: &str = r#"```This is alt-text
Here goes the pre-formatted text.
This continues the pre-formatted text on a new line after a blank line.
```
# This is a heading
This is some text.
This is more text after a blank line.
* This is a single list item.
* This is the next list item.
* This is a new list.
* This is the next item on the new list.
## This is a sub-heading
> This is a blockquote.
### This is a sub-sub-heading.
=> gemini://gem.rest/ This is a link to GemRest
=> /somewhere
That was a link without text."#;

fn main() {
// Convert the Gemtext to HTML
let html =
germ::convert::from_string(EXAMPLE_GEMTEXT, &germ::convert::Target::HTML);
let html = germ::convert::from_string(
germ::EXAMPLE_GEMTEXT,
&germ::convert::Target::HTML,
);

// Write the HTML to a file
std::fs::write("examples/convert.html", html)
Expand Down
31 changes: 1 addition & 30 deletions examples/markdown.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,39 +19,10 @@
//! This example demonstrates Germ's capabilities for converting Gemtext to
//! Markdown.
const EXAMPLE_GEMTEXT: &str = r#"```This is alt-text
Here goes the pre-formatted text.
This continues the pre-formatted text on a new line after a blank line.
```
# This is a heading
This is some text.
This is more text after a blank line.
* This is a single list item.
* This is the next list item.
* This is a new list.
* This is the next item on the new list.
## This is a sub-heading
> This is a blockquote.
### This is a sub-sub-heading.
=> gemini://gem.rest/ This is a link to GemRest
=> /somewhere
That was a link without text."#;

fn main() {
// Convert the Gemtext to Markdown
let html = germ::convert::from_string(
EXAMPLE_GEMTEXT,
germ::EXAMPLE_GEMTEXT,
&germ::convert::Target::Markdown,
);

Expand Down
12 changes: 6 additions & 6 deletions src/ast/container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ impl Ast {
// Match the first character of the Gemtext line to understand the line
// type
match line.get(0..1).unwrap_or("") {
"=" => {
"=" if !*in_preformatted => {
// If the Gemtext line starts with an "=" ("=>"), it is a link line,
// so splitting it up should be easy enough.
let line = line.get(2..).unwrap();
Expand All @@ -211,7 +211,7 @@ impl Ast {

break;
}
"#" => {
"#" if !*in_preformatted => {
// If the Gemtext line starts with an "#", it is a heading, so let's
// find out how deep it goes.
let level =
Expand All @@ -234,7 +234,7 @@ impl Ast {

break;
}
"*" => {
"*" if !*in_preformatted => {
// If the Gemtext line starts with an asterisk, it is a list item, so
// let's enter a list context.
if !*in_list {
Expand All @@ -249,7 +249,7 @@ impl Ast {
break;
}
}
">" => {
">" if !*in_preformatted => {
// If the Gemtext line starts with an ">", it is a blockquote, so
// let's just clip off the line identifier.
nodes.push(Node::Blockquote(
Expand All @@ -259,8 +259,8 @@ impl Ast {
break;
}
"`" => {
// If the Gemtext line starts with a backtick, it is a list item, so
// let's enter a preformatted text context.
// If the Gemtext line starts with a backtick, it's a preformatted
// toggle, so let's enter a preformatted text context.
*in_preformatted = !*in_preformatted;

if *in_preformatted {
Expand Down
44 changes: 44 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,47 @@
#[cfg(feature = "meta")] pub mod meta;

#[cfg(feature = "quick")] pub mod quick;

#[cfg(feature = "example-gemtext")]
pub const EXAMPLE_GEMTEXT: &str = r"```This is alt-text
Here goes the pre-formatted text.
This continues the pre-formatted text on a new line after a blank line.
```
# This is a heading
This is some text.
This is more text after a blank line.
* This is a single list item.
* This is the next list item.
* This is a new list.
* This is the next item on the new list.
## This is a sub-heading
> This is a blockquote.
### This is a sub-sub-heading.
=> gemini://gem.rest/ This is a link to GemRest
=> /somewhere
```This is a preformatted block containing inner Gemtext.
=> gemini://fuwn.me/ This is a link.
* This is a list item.
> This is a blockquote.
# This is a heading.
## This is a sub-heading.
### This is a sub-sub-heading.
```
That was a link without text.";
69 changes: 17 additions & 52 deletions tests/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,69 +18,34 @@

#[cfg(test)]
mod test {
use germ::ast::{Ast, Node};

const EXAMPLE_GEMTEXT: &str = r#"```This is alt-text
Here goes the pre-formatted text.
This continues the pre-formatted text on a new line after a blank line.
```
# This is a heading
This is some text.
This is more text after a blank line.
* This is a single list item.
* This is the next list item.
* This is a new list.
* This is the next item on the new list.
## This is a sub-heading
> This is a blockquote.
### This is a sub-sub-heading.
=> gemini://gem.rest/ This is a link to GemRest
=> /somewhere
That was a link without text."#;
use germ::{
ast::{Ast, Node},
EXAMPLE_GEMTEXT,
};

#[test]
fn build_multi_line_list_with_text() {
assert_eq!(
*Ast::from_string("* item1\n* 2\nhi text").inner(),
vec![
Node::List(vec!["item1".to_string(), "2".to_string()]),
Node::Text("hi text".to_string()),
],
);
assert_eq!(*Ast::from_string("* item1\n* 2\nhi text").inner(), vec![
Node::List(vec!["item1".to_string(), "2".to_string()]),
Node::Text("hi text".to_string()),
],);
}

#[test]
fn build_multi_line_vec() {
assert_eq!(
*Ast::from_string("=> /test hi\nhi there\n> hi").inner(),
vec![
Node::Link { to: "/test".to_string(), text: Some("hi".to_string()) },
Node::Text("hi there".to_string()),
Node::Blockquote("hi".to_string()),
],
);
assert_eq!(*Ast::from_string("=> /test hi\nhi there\n> hi").inner(), vec![
Node::Link { to: "/test".to_string(), text: Some("hi".to_string()) },
Node::Text("hi there".to_string()),
Node::Blockquote("hi".to_string()),
],);
}

#[test]
fn build_single_0th_from_vec() {
assert_eq!(
Ast::from_string("=> /test hi").inner(),
&vec![Node::Link {
to: "/test".to_string(),
text: Some("hi".to_string()),
}],
);
assert_eq!(Ast::from_string("=> /test hi").inner(), &vec![Node::Link {
to: "/test".to_string(),
text: Some("hi".to_string()),
}],);
}

#[test]
Expand Down
4 changes: 2 additions & 2 deletions tests/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ mod test {
fn node_to_gemtext() {
assert_eq!(
germ::ast::Node::Link {
to: "/faq".to_string(),
text: Some("FAQ".to_string())
to: "/faq".to_string(),
text: Some("FAQ".to_string()),
}
.to_gemtext(),
"=> /faq FAQ",
Expand Down

0 comments on commit fedb341

Please sign in to comment.