schemaorg_rs/profiles/
baseline.rs1use crate::types::{SchemaNode, SchemaValue};
7use crate::validation::diagnostics::{DiagnosticCode, Severity, ValidationDiagnostic};
8
9use super::google::common::{has_non_empty_property, recommend_property, require_one_of};
10use super::{NodeProfileResult, Profile, TypeEligibility};
11
12pub struct BaselineProfile;
14
15impl Profile for BaselineProfile {
16 fn name(&self) -> &'static str {
17 "baseline"
18 }
19
20 fn version(&self) -> &'static str {
21 "2026-04-01"
22 }
23
24 fn source_url(&self) -> &'static str {
25 "https://schema.org/docs/gs.html"
26 }
27
28 fn supported_types(&self) -> &[&str] {
29 &["Thing"]
31 }
32
33 fn evaluate_node(
34 &self,
35 node: &SchemaNode,
36 _vocab_diagnostics: &[ValidationDiagnostic],
37 ) -> NodeProfileResult {
38 let type_name = node.types.first().map_or("Thing", |t| t.as_str());
39 let path = type_name;
40 let mut diagnostics = Vec::new();
41 let mut recommended_missing = Vec::new();
42
43 if let Some(d) = require_one_of(node, &["name", "headline"], path, Severity::Warning) {
45 recommended_missing.push("name/headline".to_string());
46 diagnostics.push(d);
47 }
48
49 if let Some(d) = recommend_property(node, "image", path) {
51 recommended_missing.push("image".to_string());
52 diagnostics.push(d);
53 }
54
55 if let Some(d) = recommend_property(node, "description", path) {
57 recommended_missing.push("description".to_string());
58 diagnostics.push(d);
59 }
60
61 check_url_https(node, "url", path, &mut diagnostics);
63 check_url_https(node, "image", path, &mut diagnostics);
64
65 let eligible = !diagnostics.iter().any(|d| d.severity == Severity::Error);
66
67 NodeProfileResult {
68 type_eligibility: TypeEligibility {
69 schema_type: type_name.to_string(),
70 eligible,
71 required_missing: Vec::new(),
72 recommended_missing,
73 field_diagnostics: diagnostics,
74 },
75 }
76 }
77}
78
79fn check_url_https(
81 node: &SchemaNode,
82 prop: &str,
83 path: &str,
84 diagnostics: &mut Vec<ValidationDiagnostic>,
85) {
86 if !has_non_empty_property(node, prop) {
87 return;
88 }
89
90 if let Some(values) = node.properties.get(prop) {
91 for value in values {
92 if let SchemaValue::Url(url) = value {
93 if url.starts_with("http://") {
94 diagnostics.push(ValidationDiagnostic {
95 path: format!("{path}.{prop}"),
96 severity: Severity::Warning,
97 code: DiagnosticCode::InvalidFieldValue,
98 message: format!("URL should use HTTPS instead of HTTP: {url}"),
99 source_location: None,
100 });
101 }
102 }
103 }
104 }
105}