omena_query/style/
origin_inputs.rs1use omena_cascade::CascadeOriginV0;
2use omena_query_checker_orchestrator::OmenaCheckerCascadeDeclarationInputV0;
3use serde::Serialize;
4
5use super::cascade_checker::collect_query_checker_cascade_declarations;
6
7const HTML_STANDARD_USER_AGENT_SAMPLE_CSS: &str =
8 include_str!("../../data/html-standard-user-agent-sample/stylesheet.css");
9
10#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
11#[serde(rename_all = "camelCase")]
12pub struct OmenaQueryCascadeOriginStylesheetV0 {
13 pub schema_version: &'static str,
14 pub product: &'static str,
15 pub source_name: String,
16 pub origin: CascadeOriginV0,
17 #[serde(skip_serializing_if = "Option::is_none")]
18 pub source_url: Option<String>,
19 #[serde(skip_serializing_if = "Option::is_none")]
20 pub source_pin: Option<String>,
21 #[serde(skip_serializing_if = "Option::is_none")]
22 pub license: Option<&'static str>,
23 pub declarations: Vec<OmenaCheckerCascadeDeclarationInputV0>,
24}
25
26pub fn summarize_omena_query_cascade_origin_stylesheet_v0(
27 source_name: impl Into<String>,
28 source: &str,
29 origin: CascadeOriginV0,
30) -> OmenaQueryCascadeOriginStylesheetV0 {
31 let declarations = collect_query_checker_cascade_declarations(source)
32 .into_iter()
33 .map(|mut declaration| {
34 declaration.input.origin = origin;
35 declaration.input
36 })
37 .collect();
38 OmenaQueryCascadeOriginStylesheetV0 {
39 schema_version: "0",
40 product: "omena-query.cascade-origin-stylesheet",
41 source_name: source_name.into(),
42 origin,
43 source_url: None,
44 source_pin: None,
45 license: None,
46 declarations,
47 }
48}
49
50pub fn summarize_html_standard_user_agent_sample_v0() -> OmenaQueryCascadeOriginStylesheetV0 {
51 let mut summary = summarize_omena_query_cascade_origin_stylesheet_v0(
52 "html-standard-rendering-sample",
53 HTML_STANDARD_USER_AGENT_SAMPLE_CSS,
54 CascadeOriginV0::UserAgent,
55 );
56 summary.source_url =
57 Some("https://html.spec.whatwg.org/multipage/rendering.html#flow-content-3".to_string());
58 summary.source_pin = Some("whatwg/html@9377fd656f519b60524b92f09bcc9e6d937b2017".to_string());
59 summary.license = Some("BSD-3-Clause");
60 summary
61}
62
63#[cfg(test)]
64mod tests {
65 use super::*;
66
67 #[test]
68 fn projects_user_stylesheets_through_the_shared_cascade_input_contract() {
69 let summary = summarize_omena_query_cascade_origin_stylesheet_v0(
70 "workspace-user-styles",
71 ".card { color: green !important; }",
72 CascadeOriginV0::User,
73 );
74
75 assert_eq!(summary.declarations.len(), 1);
76 assert_eq!(summary.declarations[0].origin, CascadeOriginV0::User);
77 assert!(summary.declarations[0].important);
78 let user_json = serde_json::to_value(&summary.declarations[0]).unwrap_or_default();
79 assert_eq!(user_json.get("origin"), Some(&serde_json::json!("user")));
80
81 let author = summarize_omena_query_cascade_origin_stylesheet_v0(
82 "author-styles",
83 ".card { color: green; }",
84 CascadeOriginV0::Author,
85 );
86 let author_json = serde_json::to_value(&author.declarations[0]).unwrap_or_default();
87 assert!(author_json.get("origin").is_none());
88 }
89
90 #[test]
91 fn projects_the_licensed_html_sample_as_user_agent_input() {
92 let summary = summarize_html_standard_user_agent_sample_v0();
93
94 assert!(summary.declarations.len() >= 8);
95 assert!(
96 summary
97 .declarations
98 .iter()
99 .all(|declaration| declaration.origin == CascadeOriginV0::UserAgent)
100 );
101 assert_eq!(summary.license, Some("BSD-3-Clause"));
102 assert!(
103 summary
104 .source_pin
105 .as_deref()
106 .is_some_and(|pin| pin.starts_with("whatwg/html@"))
107 );
108 }
109}