diff --git a/Cargo.lock b/Cargo.lock
index 7d44745..7f1d35a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -932,6 +932,7 @@ dependencies = [
"html2md",
"log",
"megalodon",
+ "regex",
"rss",
"rustyline",
"tokio",
diff --git a/Cargo.toml b/Cargo.toml
index 945b07c..0d41947 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,6 +13,7 @@ env_logger = "0.10.0"
html2md = "0.2.14"
log = "0.4.19"
megalodon = "0.8.3"
+regex = "1.9.1"
rss = "2.0.4"
rustyline = "12.0.0"
tokio = { version = "1.28.2", features = ["default", "full"] }
diff --git a/src/format.rs b/src/format.rs
index 405561b..a6b50c3 100644
--- a/src/format.rs
+++ b/src/format.rs
@@ -6,6 +6,7 @@ use megalodon::{
response::Response,
Megalodon,
};
+use regex::{Captures, Regex};
use rustyline::DefaultEditor;
use url::Url;
use url_open::UrlOpen;
@@ -19,7 +20,7 @@ pub(super) async fn format_status(
"{}
> {}{}",
status.created_at.with_timezone(&Local).format("%H:%M"),
- parse_html(&status.content).trim(),
+ apply_block_quote(1, (&status.content).trim()),
format_attachments(1, &status.media_attachments)
);
let Response { json, .. } = client.get_status_context(status.id.clone(), None).await?;
@@ -35,7 +36,7 @@ pub(super) async fn format_status(
> {}
>> {}{}",
status.created_at.with_timezone(&Local).format("%H:%M"),
- parse_html(&status.content).trim(),
+ apply_block_quote(2, parse_html(&status.content).trim()),
format_attachments(2, &status.media_attachments)
)
})
@@ -52,8 +53,11 @@ pub(super) async fn format_status(
))
}
+fn quote_prefix(depth: usize) -> String {
+ vec![">"; depth].join("")
+}
+
fn format_attachments(depth: usize, attachments: &[Attachment]) -> String {
- let prefix = vec![">"; depth].join("");
if attachments.is_empty() {
String::default()
} else {
@@ -69,10 +73,76 @@ fn format_attachments(depth: usize, attachments: &[Attachment]) -> String {
} else {
a.url.clone()
};
- format!("{} ", prefix, src)
+ format!("{} ", quote_prefix(depth), src)
})
.collect::
", "\n\n"); + let content = content.replace("
", ""); + let content = content.replace("
", ""); + // replace separately to avoid trailing spaces when replacing empty lines with the prefix + let content = empty.replace(content.as_ref(), format!("\n{}\n", prefix)); + let content = non_empty.replace_all(&content, |c: &Captures| { + format!("\n{} {}", prefix, c["initial"].to_string()) + }); + content.to_string() +} + +#[cfg(test)] +mod test { + use crate::format::apply_block_quote; + + #[test] + fn test_apply_bq() { + assert_eq!( + "Foo +> +> Bar" + .to_owned(), + apply_block_quote( + 1, "Foo + +Bar" + ) + ); + } + + #[test] + fn test_apply_bq_deeper() { + assert_eq!( + "Foo +>> +>> Bar" + .to_owned(), + apply_block_quote( + 2, "Foo + +Bar" + ) + ); + } + + #[test] + fn test_apply_bq_strip_ps() { + assert_eq!( + "Foo +>> +>> Bar" + .to_owned(), + apply_block_quote(2, "Foo
Bar
") + ); + } +} diff --git a/src/main.rs b/src/main.rs index f8adbee..be22d03 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,12 +27,12 @@ mod range; #[derive(Debug, Parser)] #[command()] struct Config { - #[arg(short, long, env = "MASTODON_URL")] + #[arg(short, long, env = "MASTODON_URL", required = true)] url: String, - #[arg(short, long, env = "MASTODON_ACCESS_TOKEN")] + #[arg(short, long, env = "MASTODON_ACCESS_TOKEN", required = true)] access_token: String, #[arg(short, long)] - output_dir: String, + output_dir: Option