use crate::mf2;
use mf2::types::PropertyValue;
use mf2::types::{Fragment, Item};
use serde::{Deserialize, Serialize};
pub mod representative_hcard;
pub mod ptd;
pub mod link_rel;
#[cfg(feature = "experimental_authorship")]
pub mod authorship;
#[derive(Clone, Debug, Serialize, Deserialize, Default, PartialEq, Eq)]
pub struct Properties(pub serde_json::Map<String, serde_json::Value>);
impl std::ops::Deref for Properties {
type Target = serde_json::Map<String, serde_json::Value>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl std::ops::DerefMut for Properties {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl From<Properties> for serde_json::Value {
fn from(val: Properties) -> Self {
serde_json::Value::Object(val.0)
}
}
impl TryFrom<serde_json::Value> for Properties {
type Error = serde_json::Error;
fn try_from(val: serde_json::Value) -> Result<Self, Self::Error> {
serde_json::from_value::<Self>(val)
}
}
impl Properties {
pub fn normalize(&self) -> Properties {
if self.contains_key("properties") {
Properties(
self.get("properties")
.and_then(|p| p.as_object().cloned())
.unwrap_or_default(),
)
} else {
self.clone()
}
}
}
pub fn extract_urls(item: &Item) -> Vec<url::Url> {
let mut all_urls = vec![];
all_urls.extend(
item.children
.iter()
.filter_map(|child| child.value.to_owned())
.filter_map(|v| match v {
microformats::types::ValueKind::Url(u) => Some(u),
microformats::types::ValueKind::Plain(_) => None,
}),
);
for property_values in item.properties.values() {
for v in property_values {
match v {
PropertyValue::Url(u) => {
all_urls.push(url::Url::clone(u));
}
PropertyValue::Item(i) => {
all_urls.extend(extract_urls(i));
}
PropertyValue::Fragment(Fragment { links, .. }) => {
all_urls.extend(links.iter().filter_map(|v| v.parse().ok()));
}
_ => {}
}
}
}
all_urls
}
#[test]
fn extract_urls_test() {
let item_result = Item::try_from(serde_json::json!({
"type": ["h-entry"],
"properties": {
"content": [{"html": "Well this is a link <a href='http://example.com/3'>fooo</a>", "value": "Well this is a link fooo"}],
"like-of": ["http://example.com/", "http://example.com/2"]
}
}));
assert_eq!(item_result.as_ref().err(), None);
let item = item_result.unwrap();
assert_eq!(extract_urls(&item).len(), 2);
}