feat(npf): prototype image support

This commit is contained in:
Gustavo "Guz" L. de Mello
2024-04-29 14:50:06 -03:00
parent 13425b31e4
commit 21e42dec52
4 changed files with 134 additions and 12 deletions

43
Cargo.lock generated
View File

@@ -636,6 +636,8 @@ dependencies = [
"color-art",
"comrak",
"itertools",
"mime_guess",
"mime_serde_shim",
"serde",
"serde_json",
"serde_with",
@@ -649,6 +651,32 @@ version = "2.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
[[package]]
name = "mime"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
[[package]]
name = "mime_guess"
version = "2.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef"
dependencies = [
"mime",
"unicase",
]
[[package]]
name = "mime_serde_shim"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab9c5b33b135e34aab675cef7f678c688b30740ba299d75e3a8c0af89b5d5cea"
dependencies = [
"mime",
"serde",
]
[[package]]
name = "miniz_oxide"
version = "0.7.2"
@@ -1094,6 +1122,15 @@ version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a"
[[package]]
name = "unicase"
version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89"
dependencies = [
"version_check",
]
[[package]]
name = "unicode-bidi"
version = "0.3.15"
@@ -1145,6 +1182,12 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "walkdir"
version = "2.5.0"

View File

@@ -11,6 +11,8 @@ clio = { version = "0.3.5", features = ["clap-parse"] }
color-art = "0.3.8"
comrak = "0.21.0"
itertools = "0.12.1"
mime_guess = "2.0.4"
mime_serde_shim = "0.2.2"
serde = { version = "1.0.197", features = ["derive"] }
serde_json = "1.0.114"
serde_with = { version = "3.7.0", features = [ "macros" ] }

View File

@@ -1,4 +1,4 @@
use std::cell::RefCell;
use std::{borrow::Borrow, cell::RefCell, path, str::FromStr};
use comrak::{
arena_tree::{Children, Node},
@@ -13,12 +13,11 @@ pub mod text_formatting;
mod objects_post;
use content_blocks::{BlockText, BlockValue};
use content_blocks::{BlockImage, BlockText, BlockValue};
use objects::{BlogInfo, Media};
use text_formatting::{FormatTypeBold, FormatTypeItalic, FormatValue};
use text_formatting::{FormatTypeLink, FormatTypeStrikeThrough};
use self::{objects::BlogInfo, text_formatting::FormatTypeMention};
use text_formatting::{FormatTypeLink, FormatTypeMention, FormatTypeStrikeThrough};
#[derive(Debug)]
pub enum NPFConvertError {
@@ -164,6 +163,53 @@ impl<'a> TryFrom<&'a Node<'a, RefCell<Ast>>> for objects::Post {
post.content.push(BlockValue::Text(BlockText::from("\n")));
Ok(post)
}
NodeValue::Image(i) => {
let alt_text = Self::try_from(node.children())?.fold_content();
if let Some(p) = node.parent() {
if let NodeValue::Paragraph = p.data.borrow().value {
let alt_text = alt_text
.content
.iter()
.find(|b| {
if let BlockValue::Text(_) = b {
true
} else {
false
}
})
.unwrap_or(BlockValue::Text(BlockText::new("")).borrow())
.to_owned();
let alt_text = if let BlockValue::Text(t) = alt_text {
Some(t.text.clone())
} else {
None
};
let media = if let Ok(url) = url::Url::from_str(&i.url) {
Media::from(url)
} else if let Some(name) = path::Path::new(&i.url).file_name() {
if let Some(name) = name.to_str() {
Media::from(name)
} else {
Media::from(i.url.as_str())
}
} else {
Media::from(i.url.as_str())
};
let mut block = BlockImage::from(media);
block.alt_text = alt_text;
let mut post = Self::new(0);
post.content.push(BlockValue::Image(block));
Ok(post)
} else {
Ok(alt_text)
}
} else {
Ok(alt_text)
}
}
_ => Ok(Self::new(0)),
}
}
@@ -411,7 +457,7 @@ mod tests {
let markdown = "If **you** are reading this, thanks for giving a look\n\
and checking the ~~ugly~~ source code of this *little\n\
**personal** project*. It is heart warming to know that *at least*\n\
[someone](t:_YENQUPzd_oPpmVDqZQ-yw) found this interesting and maybe useful, even knowing\n\
[someone](t:_YENQUPzd_oPpmVDqZQ-yw) found this interesting and maybe useful, ![even knowing](image.png)\n\
how niched this whole project is.\\
- [Gustavo \"Guz\" L. de Mello](https://guz.one), Apr 16, 12.2024";

View File

@@ -1,6 +1,7 @@
use serde::{Deserialize, Serialize};
pub use super::objects_post::Post;
use mime_serde_shim::Wrapper as Mime;
#[serde_with::skip_serializing_none]
#[derive(Debug, Deserialize, Serialize, Clone)]
@@ -78,8 +79,9 @@ pub struct Avatar {
#[serde_with::skip_serializing_none]
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct Media {
pub r#type: Option<String>,
pub url: url::Url,
pub r#type: Option<Mime>,
pub url: Option<url::Url>,
pub identifier: Option<String>,
pub width: Option<u64>,
pub height: Option<u64>,
pub original_dimensions_missing: Option<bool>,
@@ -87,13 +89,17 @@ pub struct Media {
pub has_original_dimentions: Option<bool>,
}
impl Media {
pub fn new(url: url::Url) -> Self {
Self::from(url)
pub fn new(identifier: String) -> Self {
Self::from(identifier)
}
pub fn is_valid(&self) -> bool {
self.url.is_some() || self.identifier.is_some()
}
fn default() -> Self {
Self {
r#type: None,
url: url::Url::parse("https://tumblr.com").unwrap(),
url: None,
identifier: None,
width: None,
height: None,
original_dimensions_missing: None,
@@ -102,10 +108,35 @@ impl Media {
}
}
}
impl From<String> for Media {
fn from(value: String) -> Self {
let mime = if let Some(m) = mime_guess::from_path(&value).first() {
Some(Mime::from(m))
} else {
None
};
Self {
r#type: mime,
identifier: Some(value),
..Self::default()
}
}
}
impl From<&str> for Media {
fn from(value: &str) -> Self {
Self::from(String::from(value))
}
}
impl From<url::Url> for Media {
fn from(value: url::Url) -> Self {
let mime = if let Some(m) = mime_guess::from_path(&value.to_string()).first() {
Some(Mime::from(m))
} else {
None
};
Self {
url: value,
r#type: mime,
url: Some(value),
..Self::default()
}
}