aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFuwn <[email protected]>2022-06-02 07:31:20 +0000
committerFuwn <[email protected]>2022-06-02 07:31:20 +0000
commit53f1753db91fe9347155f8192052e30baaad9cbc (patch)
treef7053185a4a2e20a9a086ab96153bc074f7e5672
parentdocs(cargo): bump 0.2.3 -> 0.2.4 (diff)
downloadgerm-53f1753db91fe9347155f8192052e30baaad9cbc.tar.xz
germ-53f1753db91fe9347155f8192052e30baaad9cbc.zip
feat(ast): Ast::to_gemtext
-rw-r--r--examples/ast_to_gemtext.rs53
-rw-r--r--src/ast.rs58
-rw-r--r--src/convert/markdown.rs2
-rw-r--r--tests/ast.rs39
4 files changed, 151 insertions, 1 deletions
diff --git a/examples/ast_to_gemtext.rs b/examples/ast_to_gemtext.rs
new file mode 100644
index 0000000..5ceef21
--- /dev/null
+++ b/examples/ast_to_gemtext.rs
@@ -0,0 +1,53 @@
+// This file is part of Germ <https://github.com/gemrest/germ>.
+// Copyright (C) 2022-2022 Fuwn <[email protected]>
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 3.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+// Copyright (C) 2022-2022 Fuwn <[email protected]>
+// SPDX-License-Identifier: GPL-3.0-only
+
+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() {
+ println!(
+ "{}",
+ germ::ast::Ast::from_string(EXAMPLE_GEMTEXT).to_gemtext()
+ );
+}
diff --git a/src/ast.rs b/src/ast.rs
index f432666..49ee1f6 100644
--- a/src/ast.rs
+++ b/src/ast.rs
@@ -215,6 +215,64 @@ impl Ast {
}
}
+ #[must_use]
+ pub fn to_gemtext(&self) -> String {
+ let mut gemtext = "".to_string();
+
+ for node in &self.inner {
+ match node {
+ Node::Text(text) => gemtext.push_str(&format!("{}\n", text)),
+ Node::Link {
+ to,
+ text,
+ } =>
+ gemtext.push_str(&format!(
+ "=> {}{}\n",
+ to,
+ text
+ .clone()
+ .map_or_else(|| "".to_string(), |text| format!(" {}", text)),
+ )),
+ Node::Heading {
+ level,
+ text,
+ } =>
+ gemtext.push_str(&format!(
+ "{} {}\n",
+ match level {
+ 1 => "#",
+ 2 => "##",
+ 3 => "###",
+ _ => "",
+ },
+ text
+ )),
+ Node::List(items) =>
+ gemtext.push_str(&format!(
+ "{}\n",
+ items
+ .iter()
+ .map(|i| format!("* {}", i))
+ .collect::<Vec<String>>()
+ .join("\n"),
+ )),
+ Node::Blockquote(text) => gemtext.push_str(&format!("> {}\n", text)),
+ Node::PreformattedText {
+ alt_text,
+ text,
+ } =>
+ gemtext.push_str(&format!(
+ "```{}\n{}```\n",
+ alt_text.clone().unwrap_or_else(|| "".to_string()),
+ text
+ )),
+ Node::Whitespace => gemtext.push('\n'),
+ }
+ }
+
+ gemtext
+ }
+
/// The actual AST of `Ast`
///
/// # Example
diff --git a/src/convert/markdown.rs b/src/convert/markdown.rs
index c6899b7..a38da9f 100644
--- a/src/convert/markdown.rs
+++ b/src/convert/markdown.rs
@@ -69,7 +69,7 @@ pub fn convert(source: &[Node]) -> String {
text
));
}
- Node::Whitespace => markdown.push_str("\n"),
+ Node::Whitespace => markdown.push('\n'),
}
}
diff --git a/tests/ast.rs b/tests/ast.rs
index 8b3882d..5f6cd5c 100644
--- a/tests/ast.rs
+++ b/tests/ast.rs
@@ -20,6 +20,35 @@
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."#;
+
#[test]
fn build_multi_line_list_with_text() {
assert_eq!(
@@ -67,4 +96,14 @@ mod test {
},
);
}
+
+ #[test]
+ fn gemtext_to_ast_then_ast_to_gemtext() {
+ assert_eq!(
+ Ast::from_string(EXAMPLE_GEMTEXT).to_gemtext(),
+ // `to_gemtext` appends a newline to all responses, so let's make sure we
+ // account for that.
+ format!("{}\n", EXAMPLE_GEMTEXT),
+ );
+ }
}