1use hmd_core::{BlockDescriptor, MetadataField, MetadataFieldKind, ProfileDescriptor};
2use schemars::{schema_for, JsonSchema};
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
6pub struct CalloutMeta {
7 pub id: Option<String>,
8 #[serde(rename = "type")]
9 pub type_: Option<String>,
10 pub title: Option<String>,
11}
12
13#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
14pub struct AsideMeta {
15 pub id: Option<String>,
16 pub title: Option<String>,
17}
18
19#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
20pub struct DetailsMeta {
21 pub id: Option<String>,
22 pub summary: Option<String>,
23 pub open: Option<bool>,
24}
25
26#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
27pub struct FigureMeta {
28 pub id: Option<String>,
29 pub src: String,
30 pub alt: String,
31 pub caption: Option<String>,
32}
33
34#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
35pub struct CardsMeta {
36 pub id: Option<String>,
37 pub title: Option<String>,
38 pub columns: Option<u64>,
39}
40
41#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
42pub struct CardMeta {
43 pub id: Option<String>,
44 pub title: String,
45 pub href: Option<String>,
46}
47
48#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
49pub struct TabsMeta {
50 pub id: Option<String>,
51 pub title: Option<String>,
52}
53
54#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
55pub struct TabMeta {
56 pub id: Option<String>,
57 pub label: String,
58}
59
60#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
61pub struct MetricMeta {
62 pub id: Option<String>,
63 pub label: String,
64 pub value: serde_json::Value,
65 pub unit: Option<String>,
66 pub trend: Option<String>,
67}
68
69#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
70pub struct TimelineMeta {
71 pub id: Option<String>,
72 pub title: Option<String>,
73}
74
75#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
76pub struct EventMeta {
77 pub id: Option<String>,
78 pub at: Option<String>,
79 pub title: Option<String>,
80 pub kind: Option<String>,
81}
82
83#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
84#[serde(rename_all = "camelCase")]
85pub struct GeneralProfileSchema {
86 pub callout: Option<CalloutMeta>,
87 pub aside: Option<AsideMeta>,
88 pub details: Option<DetailsMeta>,
89 pub figure: Option<FigureMeta>,
90 pub cards: Option<CardsMeta>,
91 pub card: Option<CardMeta>,
92 pub tabs: Option<TabsMeta>,
93 pub tab: Option<TabMeta>,
94 pub metric: Option<MetricMeta>,
95 pub timeline: Option<TimelineMeta>,
96 pub event: Option<EventMeta>,
97}
98
99const CALLOUT_FIELDS: &[MetadataField] = &[
100 MetadataField::optional("id", MetadataFieldKind::String),
101 MetadataField::optional("type", MetadataFieldKind::String),
102 MetadataField::optional("title", MetadataFieldKind::String),
103];
104const ASIDE_FIELDS: &[MetadataField] = &[
105 MetadataField::optional("id", MetadataFieldKind::String),
106 MetadataField::optional("title", MetadataFieldKind::String),
107];
108const DETAILS_FIELDS: &[MetadataField] = &[
109 MetadataField::optional("id", MetadataFieldKind::String),
110 MetadataField::optional("summary", MetadataFieldKind::String),
111 MetadataField::optional("open", MetadataFieldKind::Boolean),
112];
113const FIGURE_FIELDS: &[MetadataField] = &[
114 MetadataField::optional("id", MetadataFieldKind::String),
115 MetadataField::required("src", MetadataFieldKind::String),
116 MetadataField::required("alt", MetadataFieldKind::String),
117 MetadataField::optional("caption", MetadataFieldKind::String),
118];
119const CARDS_FIELDS: &[MetadataField] = &[
120 MetadataField::optional("id", MetadataFieldKind::String),
121 MetadataField::optional("title", MetadataFieldKind::String),
122 MetadataField::optional("columns", MetadataFieldKind::Number),
123];
124const CARD_FIELDS: &[MetadataField] = &[
125 MetadataField::optional("id", MetadataFieldKind::String),
126 MetadataField::required("title", MetadataFieldKind::String),
127 MetadataField::optional("href", MetadataFieldKind::String),
128];
129const TABS_FIELDS: &[MetadataField] = &[
130 MetadataField::optional("id", MetadataFieldKind::String),
131 MetadataField::optional("title", MetadataFieldKind::String),
132];
133const TAB_FIELDS: &[MetadataField] = &[
134 MetadataField::optional("id", MetadataFieldKind::String),
135 MetadataField::required("label", MetadataFieldKind::String),
136];
137const METRIC_FIELDS: &[MetadataField] = &[
138 MetadataField::optional("id", MetadataFieldKind::String),
139 MetadataField::required("label", MetadataFieldKind::String),
140 MetadataField::required("value", MetadataFieldKind::Any),
141 MetadataField::optional("unit", MetadataFieldKind::String),
142 MetadataField::optional("trend", MetadataFieldKind::String),
143];
144const TIMELINE_FIELDS: &[MetadataField] = &[
145 MetadataField::optional("id", MetadataFieldKind::String),
146 MetadataField::optional("title", MetadataFieldKind::String),
147];
148const EVENT_FIELDS: &[MetadataField] = &[
149 MetadataField::optional("id", MetadataFieldKind::String),
150 MetadataField::optional("at", MetadataFieldKind::String),
151 MetadataField::optional("title", MetadataFieldKind::String),
152 MetadataField::optional("kind", MetadataFieldKind::String),
153];
154
155const CARD_CHILDREN: &[&str] = &["card"];
156const TAB_CHILDREN: &[&str] = &["tab"];
157const EVENT_CHILDREN: &[&str] = &["event"];
158
159const BLOCKS: &[BlockDescriptor] = &[
160 BlockDescriptor {
161 block_type: "callout",
162 schema_id: "https://hmd.dev/schemas/general@0.1/callout.schema.json",
163 fields: CALLOUT_FIELDS,
164 allowed_child_block_types: None,
165 },
166 BlockDescriptor {
167 block_type: "aside",
168 schema_id: "https://hmd.dev/schemas/general@0.1/aside.schema.json",
169 fields: ASIDE_FIELDS,
170 allowed_child_block_types: None,
171 },
172 BlockDescriptor {
173 block_type: "details",
174 schema_id: "https://hmd.dev/schemas/general@0.1/details.schema.json",
175 fields: DETAILS_FIELDS,
176 allowed_child_block_types: None,
177 },
178 BlockDescriptor {
179 block_type: "figure",
180 schema_id: "https://hmd.dev/schemas/general@0.1/figure.schema.json",
181 fields: FIGURE_FIELDS,
182 allowed_child_block_types: None,
183 },
184 BlockDescriptor {
185 block_type: "cards",
186 schema_id: "https://hmd.dev/schemas/general@0.1/cards.schema.json",
187 fields: CARDS_FIELDS,
188 allowed_child_block_types: Some(CARD_CHILDREN),
189 },
190 BlockDescriptor {
191 block_type: "card",
192 schema_id: "https://hmd.dev/schemas/general@0.1/card.schema.json",
193 fields: CARD_FIELDS,
194 allowed_child_block_types: None,
195 },
196 BlockDescriptor {
197 block_type: "tabs",
198 schema_id: "https://hmd.dev/schemas/general@0.1/tabs.schema.json",
199 fields: TABS_FIELDS,
200 allowed_child_block_types: Some(TAB_CHILDREN),
201 },
202 BlockDescriptor {
203 block_type: "tab",
204 schema_id: "https://hmd.dev/schemas/general@0.1/tab.schema.json",
205 fields: TAB_FIELDS,
206 allowed_child_block_types: None,
207 },
208 BlockDescriptor {
209 block_type: "metric",
210 schema_id: "https://hmd.dev/schemas/general@0.1/metric.schema.json",
211 fields: METRIC_FIELDS,
212 allowed_child_block_types: None,
213 },
214 BlockDescriptor {
215 block_type: "timeline",
216 schema_id: "https://hmd.dev/schemas/general@0.1/timeline.schema.json",
217 fields: TIMELINE_FIELDS,
218 allowed_child_block_types: Some(EVENT_CHILDREN),
219 },
220 BlockDescriptor {
221 block_type: "event",
222 schema_id: "https://hmd.dev/schemas/general@0.1/event.schema.json",
223 fields: EVENT_FIELDS,
224 allowed_child_block_types: None,
225 },
226];
227
228pub const PROFILE: ProfileDescriptor = ProfileDescriptor {
229 id: "general@0.1",
230 name: "general",
231 version: "0.1",
232 source: "official",
233 blocks: BLOCKS,
234 reference_rules: &[],
235};
236
237pub fn descriptor() -> ProfileDescriptor {
238 PROFILE
239}
240
241pub fn register_profile() -> ProfileDescriptor {
242 descriptor()
243}
244
245pub fn json_schema() -> serde_json::Value {
246 serde_json::to_value(schema_for!(GeneralProfileSchema)).expect("serializes schema")
247}