1extern crate self as ftd_rt;
2
3mod condition;
4mod dnode;
5mod event;
6mod html;
7mod ui;
8#[cfg(feature = "wasm")]
9mod wasm;
10
11pub use condition::Condition;
12pub use event::{Action, Event};
13pub use html::{anchor, color, length, overflow, Node};
14pub use ui::{
15 Anchor, AttributeType, Code, Color, Column, Common, ConditionalAttribute, ConditionalValue,
16 Container, Element, ExternalFont, FontDisplay, GradientDirection, IFrame, Image, Input, Length,
17 NamedFont, Overflow, Position, Region, Row, Scene, Style, Text, TextAlign, TextBlock,
18 TextFormat, Weight,
19};
20
21#[derive(serde::Serialize, serde::Deserialize, Eq, PartialEq, Debug, Default, Clone)]
22pub struct Rendered {
23 pub original: String,
24 pub rendered: String,
25}
26
27impl From<&str> for Rendered {
28 fn from(item: &str) -> Self {
29 Rendered {
30 original: item.to_string(),
31 rendered: item.to_string(),
32 }
33 }
34}
35
36#[derive(thiserror::Error, Debug)]
37pub enum Error {
38 #[error("invalid input: {message}")]
39 InvalidInput { message: String, context: String },
40}
41
42pub type Map = std::collections::BTreeMap<String, String>;
43type Result<T> = std::result::Result<T, Error>;
44
45#[derive(serde::Deserialize)]
46#[cfg_attr(
47 not(feature = "wasm"),
48 derive(serde::Serialize, PartialEq, Debug, Default, Clone)
49)]
50pub struct Document {
51 pub html: String,
52 pub data: ftd_rt::DataDependenciesMap,
53 pub external_children: ExternalChildrenDependenciesMap,
54}
55
56pub fn e<T, S1, S2>(m: S1, c: S2) -> Result<T>
57where
58 S1: Into<String>,
59 S2: Into<String>,
60{
61 Err(Error::InvalidInput {
62 message: m.into(),
63 context: c.into(),
64 })
65}
66
67pub fn get_name<'a, 'b>(prefix: &'a str, s: &'b str, doc_id: &str) -> ftd_rt::Result<&'b str> {
68 match s.split_once(' ') {
69 Some((p1, p2)) => {
70 if p1 != prefix {
71 return ftd_rt::e(format!("must start with {}", prefix), doc_id);
72 }
73 Ok(p2)
74 }
75 None => ftd_rt::e(
76 format!("{} does not contain space (prefix={})", s, prefix),
77 doc_id,
78 ),
79 }
80}
81
82pub type DataDependenciesMap = std::collections::BTreeMap<String, Data>;
83
84#[derive(serde::Deserialize)]
85#[cfg_attr(
86 not(feature = "wasm"),
87 derive(serde::Serialize, PartialEq, Debug, Default, Clone)
88)]
89pub struct Data {
90 pub value: String,
91 pub dependencies: ftd_rt::Map,
92}
93
94pub type ExternalChildrenDependenciesMap =
95 std::collections::BTreeMap<String, Vec<ExternalChildrenCondition>>;
96
97#[derive(serde::Deserialize)]
98#[cfg_attr(
99 not(feature = "wasm"),
100 derive(serde::Serialize, PartialEq, Debug, Default, Clone)
101)]
102pub struct ExternalChildrenCondition {
103 pub condition: Vec<String>,
104 pub set_at: String,
105}
106
107#[derive(serde::Deserialize)]
108#[cfg_attr(
109 not(feature = "wasm"),
110 derive(PartialEq, Debug, Clone, serde::Serialize)
111)]
112pub enum DependencyType {
113 Style,
114 Visible,
115 Value,
116}
117
118#[derive(serde::Deserialize)]
119#[cfg_attr(
120 not(feature = "wasm"),
121 derive(serde::Serialize, PartialEq, Debug, Clone)
122)]
123pub struct Dependencies {
124 pub dependency_type: DependencyType,
125 pub condition: Option<String>,
126 pub parameters: std::collections::BTreeMap<String, ValueWithDefault>,
127}
128
129#[derive(serde::Deserialize)]
130#[cfg_attr(
131 not(feature = "wasm"),
132 derive(serde::Serialize, PartialEq, Debug, Clone)
133)]
134pub struct ValueWithDefault {
135 pub value: ConditionalValue,
136 pub default: Option<ConditionalValue>,
137}
138
139#[cfg(test)]
140mod test {
141 #[test]
142 fn get_name() {
143 assert_eq!(super::get_name("fn", "fn foo").unwrap(), "foo")
144 }
145}