use crate::{dom, error::FullTextParserError, util::Util};
use dom_query::NodeRef;
use url::Url;
#[derive(Debug, Clone)]
pub struct ImageObject {
width: Option<u32>,
height: Option<u32>,
url: Option<Url>,
description: Option<String>,
name: Option<String>,
parent_url: Option<Url>,
}
impl ImageObject {
pub fn parse_node(node: &NodeRef) -> Option<Self> {
if !dom::tag_name_is(node, "div") {
return None;
}
let item_prop_image = dom::attr(node, "itemprop")
.map(|prop| prop == "image")
.unwrap_or(false);
let item_type_image = Util::has_schema_org_type(node, "ImageObject");
if !item_prop_image && !item_type_image {
return None;
}
let meta_nodes = dom::elements_by_tag_name(node, "meta");
let mut width = None;
let mut height = None;
let mut url = None;
let mut description = None;
let mut name = None;
let mut parent_url = None;
if let Some(parent) = node.parent()
&& dom::tag_name_is(&parent, "a")
{
let href = dom::attr(&parent, "href");
parent_url = href.and_then(|href| Url::parse(&href).ok());
}
for meta_node in meta_nodes {
let item_prop = dom::attr(&meta_node, "itemprop");
let content_prop = dom::attr(&meta_node, "content");
if let (Some(item_prop), Some(content_prop)) = (item_prop, content_prop) {
if item_prop == "width" {
width = content_prop.parse::<u32>().ok();
} else if item_prop == "height" {
height = content_prop.parse::<u32>().ok();
} else if item_prop == "url" {
url = Url::parse(&content_prop).ok();
} else if item_prop == "description" {
description = Some(content_prop);
} else if item_prop == "name" {
name = Some(content_prop);
}
}
}
url.as_ref()?;
Some(Self {
width,
height,
url,
description,
name,
parent_url,
})
}
pub fn replace(&self, node: &NodeRef) -> Result<(), FullTextParserError> {
let parent = node.parent().ok_or(FullTextParserError::Dom)?;
if dom::tag_name_is(&parent, "a") {
return self.replace(&parent);
}
let tree = node.tree;
let root = tree.new_element("imageobject");
dom::replace_with(node, &root);
let a = tree.new_element("a");
dom::append_child(&root, &a);
let img = tree.new_element("img");
dom::append_child(&a, &img);
if let Some(width) = self.width {
img.set_attr("width", &width.to_string());
}
if let Some(height) = self.height {
img.set_attr("height", &height.to_string());
}
if let Some(description) = self.description.as_deref() {
img.set_attr("alt", description);
}
if let Some(name) = self.name.as_deref() {
img.set_attr("title", name);
}
if let Some(href) = self.parent_url.as_ref().or(self.url.as_ref()) {
a.set_attr("href", href.as_str());
}
if let Some(url) = self.url.as_ref() {
img.set_attr("src", url.as_str());
}
Ok(())
}
}