moss_core/contract/
describe.rs1use serde::Serialize;
8use std::collections::BTreeMap;
9
10use crate::ast::shortcode::ShortcodeKind;
11use crate::contract::components::{COMPONENTS, Status};
12use crate::contract::frontmatter::{FrontmatterFieldJson, frontmatter_fields};
13use crate::contract::tokens::Tokens;
14
15pub const DESCRIBE_SCHEMA_VERSION: u32 = 4;
16pub const MOSS_HTML_VERSION: u32 = 1;
17
18#[derive(Serialize)]
19pub struct DescribePayload<'a> {
20 pub describe_schema_version: u32,
21 pub moss_html_version: u32,
22 pub moss_binary_version: &'static str,
23 pub tokens: BTreeMap<&'a str, Vec<TokenJson<'a>>>,
24 pub components: Vec<ComponentJson>,
25 pub frontmatter: Vec<FrontmatterFieldJson>,
26}
27
28#[derive(Serialize)]
29pub struct TokenJson<'a> {
30 pub name: &'a str,
31 pub value: &'a str,
32 #[serde(skip_serializing_if = "Option::is_none")]
33 pub dark_value: Option<&'a str>,
34 #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
35 pub type_hint: Option<&'a str>,
36 #[serde(skip_serializing_if = "Option::is_none")]
37 pub description: Option<&'a str>,
38}
39
40#[derive(Serialize)]
41pub struct ComponentJson {
42 pub class: &'static str,
43 pub kind: &'static str,
44 pub parent: &'static str,
45 pub data_attrs: Vec<DataAttrJson>,
46 pub example_html: &'static str,
47 pub example_markdown: &'static str,
48 pub status: &'static str,
49 pub since: &'static str,
50 pub description: &'static str,
51 pub authorable: bool,
56}
57
58#[derive(Serialize)]
59pub struct DataAttrJson {
60 pub name: &'static str,
61 pub values: &'static [&'static str],
62 pub default: &'static str,
63 pub description: &'static str,
64}
65
66impl<'a> DescribePayload<'a> {
67 pub fn new(tokens: &'a Tokens) -> Self {
68 let mut tokens_map: BTreeMap<&str, Vec<TokenJson>> = BTreeMap::new();
69 for group in &tokens.groups {
70 let entries: Vec<TokenJson> = group
71 .entries
72 .iter()
73 .map(|t| TokenJson {
74 name: &t.name,
75 value: &t.value,
76 dark_value: t.dark_value.as_deref(),
77 type_hint: t.type_hint.as_deref(),
78 description: t.description.as_deref(),
79 })
80 .collect();
81 tokens_map.insert(&group.name, entries);
82 }
83
84 let authorable: std::collections::HashSet<&'static str> =
85 ShortcodeKind::all().map(|k| k.root_class()).collect();
86
87 let components: Vec<ComponentJson> = COMPONENTS
88 .iter()
89 .map(|c| ComponentJson {
90 class: c.class,
91 kind: c.kind,
92 parent: c.parent,
93 data_attrs: c
94 .data_attrs
95 .iter()
96 .map(|a| DataAttrJson {
97 name: a.name,
98 values: a.values,
99 default: a.default,
100 description: a.description,
101 })
102 .collect(),
103 example_html: c.example_html,
104 example_markdown: c.example_markdown,
105 status: match c.status {
106 Status::Confirmed => "confirmed",
107 Status::Emerging => "emerging",
108 Status::Retired => "retired",
109 },
110 since: c.since,
111 description: c.description,
112 authorable: authorable.contains(c.class),
113 })
114 .collect();
115
116 DescribePayload {
117 describe_schema_version: DESCRIBE_SCHEMA_VERSION,
118 moss_html_version: MOSS_HTML_VERSION,
119 moss_binary_version: env!("CARGO_PKG_VERSION"),
120 tokens: tokens_map,
121 components,
122 frontmatter: frontmatter_fields(),
123 }
124 }
125}