microformats 0.18.0

A union library of the Microformats types and associated parser.
Documentation
use crate::parse::element::test::{from_html_str, grab_element_from_document};
use microformats_types::temporal::Stamp;

use super::*;

#[test]
fn compose_temporal_value() {
    let element = grab_element_from_document(&from_html_str("<div></div>"), "div").unwrap();
    let vcp_extractor = ValueClassPropertyExtractor {
        element: ElementPtr::new(ElementRef {
            index: 0,
            node: Node { elem: element },
        }),
        hint: TypeHint::Plain,
    };

    assert_eq!(
        vcp_extractor
            .compose_temporal_value(&["2000-10-10".to_owned(), "".to_owned(), "10:00Z".to_owned()])
            .map(|t| t.to_string()),
        Some("2000-10-10 10:00Z".to_owned())
    );
    assert_eq!(
        vcp_extractor
            .compose_temporal_value(&["2000-100".to_owned(), "10:00Z".to_owned()])
            .map(|t| t.to_string()),
        Some("2000-100 10:00Z".to_owned())
    );
}

#[yare::parameterized(
    value_img = {"img", "<img class='value' alt='A cool place to be.' />"},
    value_area = {"area", "<area class='value' alt='A cool place to be.'></area>"},
    value_data = {"data", "<data class='value' value='A cool place to be.' />"},
    value_title_span = {"span", "<span class='value-title' title='A cool place to be.'>Don't take this.</span>"},
    value_title = {"div", r#"
<p>
    <span class="h-geo">The Bricklayer's Arms
        <div class="p-latitude">
            <span class="value-title" title="A cool place to be."> </span> 
        </div>
        <span class="p-longitude">
            <span class="value-title" title="-0.14812"> </span>
        </span>
    </span>
</p>
        "#}
)]
fn text_extraction(tag: &str, html: &str) {
    let element = grab_element_from_document(&from_html_str(html), tag).unwrap();
    let vcp_extractor = ValueClassPropertyExtractor {
        element: ElementPtr::new(ElementRef {
            index: 0,
            node: Node { elem: element },
        }),
        hint: TypeHint::Plain,
    };

    assert_eq!(
        vcp_extractor.extract_value_class(&"http://example.com".parse().unwrap()),
        Ok(Some(PropertyValue::Plain(
            "A cool place to be.".to_string()
        ))),
        "extracts the text"
    );
}

#[yare::parameterized(
    ins = { "ins", "<ins datetime='$dt'></ins>", None},
    del = { "del", "<del datetime='$dt'></del>", None},
    time = { "time", "<time datetime='$dt'></time>", None},
    time_class = { "time", "<time class='dt-magic' datetime='$dt'></time>", None},
    values = { "li", r#"
<li class="dt-start">
    <time class="value" datetime="2009-06-26">26 July</time>, from
    <span class="value">07pm 
</span></li>
        "#, Stamp::from_str("2009-06-26 07pm").ok().map(temporal::Value::Timestamp) },
    value_title_date = { "p", r#"
    <p class="dt-start">
      <span class="value-title" title="2013-03-14"> </span>
      March 14th 2013
    </p>
        "#, Stamp::from_str("2013-03-14").ok().map(temporal::Value::Timestamp) },
    // Note: This test is currently ignored due to spec drift between the microformats specification
    // and the vendor test suite. The spec says timezone offset colons should be removed (XXYY format),
    // but the vendor test suite expects them preserved (XX:YY format). The code now follows the vendor
    // test suite, so this spec-compliant test fails. See:
    // https://microformats.org/wiki/value-class-pattern#Date_and_time_parsing
    // "If the offset uses XX:YY format, remove the colon so it is XXYY format."
    concat = { "span", r#"
 <span class="dt-start">
  <time class="value" datetime="2009-06-26">26 July</time>, from
  <time class="value">19:00-06:00</time>
 </span>
        "#, Stamp::from_str("2009-06-26 19:00-06:00").ok().map(temporal::Value::Timestamp)}

)]
fn datetime(
    tag: &str,
    html: &str,
    expecting_dt: Option<temporal::Value>,
) -> Result<(), crate::Error> {
    let stamp = expecting_dt.unwrap_or_else(|| temporal::Value::Timestamp(Stamp::now()));
    let dt = stamp.to_string();
    let element =
        grab_element_from_document(&from_html_str(&html.replace("$dt", &dt)), tag).unwrap();
    let vcp_extractor = ValueClassPropertyExtractor {
        element: ElementPtr::new(ElementRef {
            index: 0,
            node: Node { elem: element },
        }),
        hint: TypeHint::Temporal,
    };

    assert_eq!(
        vcp_extractor.extract_value_class(&"http://example.com".parse().unwrap()),
        Ok(Some(PropertyValue::Temporal(stamp))),
        "extracts the timestamp"
    );

    Ok(())
}