schemaorg_rs/profiles/google/
article.rs1use crate::types::SchemaNode;
7use crate::validation::ValidationDiagnostic as VD;
8
9use super::common::{recommend_property, require_property, validate_nested};
10use crate::profiles::{NodeProfileResult, Profile, TypeEligibility};
11
12pub struct GoogleArticleProfile;
17
18impl Profile for GoogleArticleProfile {
19 fn name(&self) -> &'static str {
20 "google"
21 }
22
23 fn version(&self) -> &'static str {
24 "2026-04-01"
25 }
26
27 fn source_url(&self) -> &'static str {
28 "https://developers.google.com/search/docs/appearance/structured-data/article"
29 }
30
31 fn supported_types(&self) -> &[&str] {
32 &[
33 "Article",
34 "NewsArticle",
35 "BlogPosting",
36 "TechArticle",
37 "ScholarlyArticle",
38 ]
39 }
40
41 fn evaluate_node(&self, node: &SchemaNode, _vocab_diagnostics: &[VD]) -> NodeProfileResult {
42 let type_name = node.types.first().map_or("Article", |t| t.as_str());
43 let path = type_name;
44 let mut diagnostics = Vec::new();
45 let mut required_missing = Vec::new();
46 let mut recommended_missing = Vec::new();
47
48 for prop in &["headline", "image", "datePublished", "author"] {
50 if let Some(d) = require_property(node, prop, path) {
51 required_missing.push((*prop).to_string());
52 diagnostics.push(d);
53 }
54 }
55
56 for prop in &["dateModified", "publisher", "mainEntityOfPage"] {
58 if let Some(d) = recommend_property(node, prop, path) {
59 recommended_missing.push((*prop).to_string());
60 diagnostics.push(d);
61 }
62 }
63
64 let author_diags = validate_nested(node, "author", "Person", &["name"], &["url"], path);
66 diagnostics.extend(author_diags);
67
68 let publisher_diags = validate_nested(
70 node,
71 "publisher",
72 "Organization",
73 &["name"],
74 &["logo"],
75 path,
76 );
77 diagnostics.extend(publisher_diags);
78
79 let eligible = required_missing.is_empty();
80
81 NodeProfileResult {
82 type_eligibility: TypeEligibility {
83 schema_type: type_name.to_string(),
84 eligible,
85 required_missing,
86 recommended_missing,
87 field_diagnostics: diagnostics,
88 },
89 }
90 }
91}