diff --git a/acrate_astreams/src/activitystreams/jsonld.rs b/acrate_astreams/src/activitystreams/jsonld.rs index fb4ad3e..ba84642 100644 --- a/acrate_astreams/src/activitystreams/jsonld.rs +++ b/acrate_astreams/src/activitystreams/jsonld.rs @@ -16,6 +16,7 @@ pub trait StreamsJsonLD { fn jsonld_iter_value_langstring(&self, id: &Iri) -> impl Iterator>; fn jsonld_any_value_mediatype(&self, id: &Iri) -> Option>; fn jsonld_any_node_string(&self, id: &Iri) -> Option>; + fn jsonld_any_value_langtag(&self, id: &Iri) -> Option>; } impl StreamsJsonLD for &json_ld::Node { @@ -112,12 +113,12 @@ impl StreamsJsonLD for &json_ld::Node { Some(value) => value, }; - let string = match value.as_str() { + let r#str = match value.as_str() { None => return Some(Err(anyhow!("Couldn't process property as JSON-LD string"))), - Some(string) => string + Some(r#str) => r#str }; - let mediatype = match MediaType::parse(string) { + let mediatype = match MediaType::parse(r#str) { Err(e) => return Some(Err(Error::from(e).context("Couldn't parse property as MIME media type"))), Ok(mediatype) => mediatype, }; @@ -145,6 +146,32 @@ impl StreamsJsonLD for &json_ld::Node { Some(Ok(string)) } + + fn jsonld_any_value_langtag(&self, id: &Iri) -> Option> { + let property = match self.properties.get_any(&id) { + None => return None, + Some(property) => property, + }; + + let value = match property.as_value() { + None => return Some(Err(anyhow!("Couldn't process property as JSON-LD value"))), + Some(value) => value, + }; + + let r#str = match value.as_str() { + None => return Some(Err(anyhow!("Couldn't process property as JSON-LD string"))), + Some(r#str) => r#str + }; + + let string = r#str.to_string(); + + let langtag = match LangTagBuf::new(string) { + Err(e) => return Some(Err(anyhow!("Couldn't process property as a BCP47 language tag: {e:#?}"))), + Ok(langtag) => langtag, + }; + + Some(Ok(langtag)) + } } impl StreamsLink for &json_ld::Node { @@ -171,4 +198,10 @@ impl StreamsLink for &json_ld::Node { iri!("https://www.w3.org/ns/activitystreams#name") ) } + + fn activitystreams_hreflang(&self) -> Option> { + self.jsonld_any_value_langtag( + iri!("https://www.w3.org/ns/activitystreams#hreflang") + ) + } } diff --git a/acrate_astreams/src/activitystreams/mod.rs b/acrate_astreams/src/activitystreams/mod.rs index b844a7c..8021876 100644 --- a/acrate_astreams/src/activitystreams/mod.rs +++ b/acrate_astreams/src/activitystreams/mod.rs @@ -13,8 +13,9 @@ use anyhow::Result as AResult; use json_ld::Direction; -use json_ld::syntax::LangTagBuf; +use json_ld::syntax::{LangTag, LangTagBuf}; use mediatype::MediaType; +use static_iref::iri; pub mod jsonld; @@ -33,4 +34,6 @@ pub trait StreamsLink { fn activitystreams_mediatype(&self) -> Option>; fn activitystreams_names(&self) -> impl Iterator, Option)>>; + + fn activitystreams_hreflang(&self) -> Option>; } diff --git a/acrate_astreams/tests/test_activitystreams.rs b/acrate_astreams/tests/test_activitystreams.rs index c5cc9fd..72dd1b5 100644 --- a/acrate_astreams/tests/test_activitystreams.rs +++ b/acrate_astreams/tests/test_activitystreams.rs @@ -1,4 +1,3 @@ -use json_ld::Direction; use json_ld::syntax::LangTagBuf; use acrate_astreams::activitystreams::jsonld::LangTriple; @@ -259,7 +258,7 @@ async fn test_link_media_type() { let node = doc.main_node() .expect("Main node was not found"); - let href = { + let mediatype = { use acrate_astreams::activitystreams::StreamsLink; node.activitystreams_mediatype() @@ -267,7 +266,7 @@ async fn test_link_media_type() { .expect("Property `mediaType` failed to process") }; - assert_eq!(href, mediatype::media_type!(TEXT/HTML)); + assert_eq!(mediatype, mediatype::media_type!(TEXT/HTML)); } #[tokio::test] @@ -287,7 +286,12 @@ async fn test_link_name_value() { .collect() }; - println!("{names:#?}"); + let mut names = names.into_iter(); + + let (name, language, direction) = names.next().expect("Expected `name` [0] to be present"); + assert_eq!(name, "A simple note"); + assert_eq!(language, None); + assert_eq!(direction, None); } #[tokio::test] @@ -307,5 +311,38 @@ async fn test_link_name_lang() { .collect() }; - println!("{names:#?}"); + let mut names = names.into_iter(); + + let (name, language, direction) = names.next().expect("Expected `name` [0] to be present"); + assert_eq!(name, "A simple note"); + assert_eq!(language, Some(LangTagBuf::new("en".to_string()).unwrap())); + assert_eq!(direction, None); + + let (name, language, direction) = names.next().expect("Expected `name` [1] to be present"); + assert_eq!(name, "Una nota sencilla"); + assert_eq!(language, Some(LangTagBuf::new("es".to_string()).unwrap())); + assert_eq!(direction, None); + + let (name, language, direction) = names.next().expect("Expected `name` [2] to be present"); + assert_eq!(name, "一段简单的笔记"); + assert_eq!(language, Some(LangTagBuf::new("zh-Hans".to_string()).unwrap())); + assert_eq!(direction, None); +} + +#[tokio::test] +async fn test_link_hreflang() { + let doc = e122::expand().await; + + let node = doc.main_node() + .expect("Main node was not found"); + + let hreflang = { + use acrate_astreams::activitystreams::StreamsLink; + + node.activitystreams_hreflang() + .expect("Property `mediaType` was not found") + .expect("Property `mediaType` failed to process") + }; + + assert_eq!(hreflang, "en") }