diff --git a/acrate_astreams/src/activitystreams/jsonld.rs b/acrate_astreams/src/activitystreams/jsonld.rs index 8ed1759..fb4ad3e 100644 --- a/acrate_astreams/src/activitystreams/jsonld.rs +++ b/acrate_astreams/src/activitystreams/jsonld.rs @@ -2,13 +2,18 @@ use anyhow::{anyhow, Error}; use static_iref::iri; use anyhow::Result as AResult; use iref::Iri; +use json_ld::Direction; use json_ld::object::Any; +use json_ld::syntax::LangTagBuf; use mediatype::MediaType; use crate::activitystreams::StreamsLink; +pub type LangTriple = (String, Option, Option); + pub trait StreamsJsonLD { fn jsonld_any_value_string(&self, id: &Iri) -> Option>; fn jsonld_iter_value_string(&self, id: &Iri) -> impl Iterator>; + 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>; } @@ -59,6 +64,43 @@ impl StreamsJsonLD for &json_ld::Node { strings } + fn jsonld_iter_value_langstring(&self, id: &Iri) -> impl Iterator> { + let properties = self.properties.get(&id); + + let values = properties.map(|v| v + .as_value() + .ok_or(anyhow!("Couldn't process property as JSON-LD value")) + ); + + let values = values.flat_map(|v| v + .map(|v| { + let string = v + .as_str() + .ok_or(anyhow!("Expected property to be a langString, but no string was obtained"))? + .to_string(); + + let lang = v + .language() + .map(|l| l + .as_well_formed() + .ok_or(anyhow!("Expected property to have a valid language tag, but got an invalid one instead")) + ); + + let lang = match lang { + None => None, + Some(Ok(lang)) => Some(lang.to_owned()), + Some(Err(err)) => return Err(err), + }; + + let direction = v.direction(); + + Ok((string, lang, direction)) + }) + ); + + values + } + fn jsonld_any_value_mediatype(&self, id: &Iri) -> Option> { let property = match self.properties.get_any(&id) { None => return None, @@ -112,7 +154,7 @@ impl StreamsLink for &json_ld::Node { ) } - fn activitystreams_rel_lenient(&self) -> impl Iterator> { + fn activitystreams_rels_lenient(&self) -> impl Iterator> { self.jsonld_iter_value_string( iri!("https://www.w3.org/ns/activitystreams#rel") ) @@ -124,9 +166,9 @@ impl StreamsLink for &json_ld::Node { ) } - /* - fn activitystreams_name(&self) -> impl Iterator, String)>> { - todo!() + fn activitystreams_names(&self) -> impl Iterator> { + self.jsonld_iter_value_langstring( + iri!("https://www.w3.org/ns/activitystreams#name") + ) } - */ } diff --git a/acrate_astreams/src/activitystreams/mod.rs b/acrate_astreams/src/activitystreams/mod.rs index 5a46f25..b844a7c 100644 --- a/acrate_astreams/src/activitystreams/mod.rs +++ b/acrate_astreams/src/activitystreams/mod.rs @@ -12,6 +12,8 @@ //! use anyhow::Result as AResult; +use json_ld::Direction; +use json_ld::syntax::LangTagBuf; use mediatype::MediaType; pub mod jsonld; @@ -26,11 +28,9 @@ pub trait StreamsLink { fn activitystreams_href(&self) -> Option>; // FIXME: This accepts any kind of string, and does not filter to HTML link relations - fn activitystreams_rel_lenient(&self) -> impl Iterator>; + fn activitystreams_rels_lenient(&self) -> impl Iterator>; fn activitystreams_mediatype(&self) -> Option>; - /* - fn streams_name(&self) -> impl Iterator>; - */ + fn activitystreams_names(&self) -> impl Iterator, Option)>>; } diff --git a/acrate_astreams/tests/test_activitystreams.rs b/acrate_astreams/tests/test_activitystreams.rs index 009b8f7..c5cc9fd 100644 --- a/acrate_astreams/tests/test_activitystreams.rs +++ b/acrate_astreams/tests/test_activitystreams.rs @@ -1,4 +1,6 @@ -use acrate_astreams::activitystreams::StreamsLink; +use json_ld::Direction; +use json_ld::syntax::LangTagBuf; +use acrate_astreams::activitystreams::jsonld::LangTriple; macro_rules! test_example { ($modname:ident, $filename:literal) => { @@ -233,7 +235,7 @@ async fn test_link_rel() { let mut rels = { use acrate_astreams::activitystreams::StreamsLink; - node.activitystreams_rel_lenient() + node.activitystreams_rels_lenient() .map(|v| v .expect("Property `rel` failed to process") ) @@ -267,3 +269,43 @@ async fn test_link_media_type() { assert_eq!(href, mediatype::media_type!(TEXT/HTML)); } + +#[tokio::test] +async fn test_link_name_value() { + let doc = e117::expand().await; + + let node = doc.main_node() + .expect("Main node was not found"); + + let names: Vec = { + use acrate_astreams::activitystreams::StreamsLink; + + node.activitystreams_names() + .map(|v| v + .expect("Property `name` failed to process") + ) + .collect() + }; + + println!("{names:#?}"); +} + +#[tokio::test] +async fn test_link_name_lang() { + let doc = e118::expand().await; + + let node = doc.main_node() + .expect("Main node was not found"); + + let names: Vec = { + use acrate_astreams::activitystreams::StreamsLink; + + node.activitystreams_names() + .map(|v| v + .expect("Property `name` failed to process") + ) + .collect() + }; + + println!("{names:#?}"); +}