1#[allow(clippy::too_many_arguments)]
2pub fn common_from_properties(
3 unresolved_properties: &ftd::Map<ftd::component::Property>,
4 doc: &ftd::p2::TDoc,
5 condition: &Option<ftd::p2::Boolean>,
6 is_child: bool,
7 events: &[ftd::p2::Event],
8 reference: Option<String>,
9) -> ftd::p1::Result<ftd::Common> {
10 let properties = &ftd::component::resolve_properties(0, unresolved_properties, doc)?;
11 let submit = ftd::p2::utils::string_optional("submit", properties, doc.name, 0)?;
12 let link = ftd::p2::utils::string_optional("link", properties, doc.name, 0)?;
13 if let (Some(_), Some(_)) = (&submit, &link) {
14 return ftd::p2::utils::e2("Cannot have both submit and link together", doc.name, 0);
15 }
16 let gradient_color_str =
17 ftd::p2::utils::string_optional("gradient-colors", properties, doc.name, 0)?;
18
19 let gradient_colors: Vec<ftd::ColorValue> = match gradient_color_str {
20 Some(f) => f
21 .split(',')
22 .flat_map(|x| color_from(Some(x.to_string()), doc.name).ok()?)
23 .collect(),
24 None => vec![],
25 };
26
27 let anchor = ftd::Anchor::from(
28 ftd::p2::utils::string_optional("anchor", properties, doc.name, 0)?,
29 doc.name,
30 )?;
31
32 let (position, inner) = {
33 let mut position = None;
34 let mut inner = match anchor {
35 Some(ref p) => match p {
36 ftd::Anchor::Parent => false,
37 ftd::Anchor::Window => true,
38 },
39 None => false,
40 };
41 let position_inner =
42 match ftd::p2::utils::string_optional("position", properties, doc.name, 0)? {
43 None => ftd::p2::utils::string_optional("align", properties, doc.name, 0)?,
44 Some(v) => Some(v),
45 };
46 if let Some(position_inner) = position_inner {
47 if let Some(p) = position_inner.strip_prefix("inner ") {
48 position = ftd::Position::from(Some(p.to_string()), doc.name)?;
49 inner = true;
50 } else {
51 position = ftd::Position::from(Some(position_inner), doc.name)?;
52 }
53 }
54 (position, inner)
55 };
56
57 let (cond, is_visible) = match condition {
58 Some(c) => {
59 let mut is_visible = true;
60 if !c.eval(0, doc)? {
61 is_visible = false;
62 }
63 if !c.is_arg_constant() {
64 (Some(c.to_condition(0, doc)?), is_visible)
65 } else {
66 (None, is_visible)
67 }
68 }
69 _ => (None, true),
70 };
71
72 Ok(ftd::Common {
73 title: ftd::p2::utils::string_optional("title", properties, doc.name, 0)?,
74 conditional_attribute: Default::default(),
75 condition: cond,
76 is_not_visible: !is_visible,
77 is_dummy: false,
78 events: ftd::p2::Event::get_events(0, events, doc)?,
79 reference,
80 region: ftd::Region::from(
81 ftd::p2::utils::string_optional("region", properties, doc.name, 0)?,
82 doc.name,
83 )?,
84 padding: ftd::p2::utils::int_optional("padding", properties, doc.name, 0)?,
85 padding_vertical: ftd::p2::utils::int_optional(
86 "padding-vertical",
87 properties,
88 doc.name,
89 0,
90 )?,
91 padding_horizontal: ftd::p2::utils::int_optional(
92 "padding-horizontal",
93 properties,
94 doc.name,
95 0,
96 )?,
97 padding_left: ftd::p2::utils::int_optional("padding-left", properties, doc.name, 0)?,
98 padding_right: ftd::p2::utils::int_optional("padding-right", properties, doc.name, 0)?,
99 padding_top: ftd::p2::utils::int_optional("padding-top", properties, doc.name, 0)?,
100 padding_bottom: ftd::p2::utils::int_optional("padding-bottom", properties, doc.name, 0)?,
101 border_top_radius: ftd::p2::utils::int_optional(
102 "border-top-radius",
103 properties,
104 doc.name,
105 0,
106 )?,
107 border_bottom_radius: ftd::p2::utils::int_optional(
108 "border-bottom-radius",
109 properties,
110 doc.name,
111 0,
112 )?,
113 border_left_radius: ftd::p2::utils::int_optional(
114 "border-left-radius",
115 properties,
116 doc.name,
117 0,
118 )?,
119 border_right_radius: ftd::p2::utils::int_optional(
120 "border-right-radius",
121 properties,
122 doc.name,
123 0,
124 )?,
125 width: ftd::Length::from(
126 ftd::p2::utils::string_optional("width", properties, doc.name, 0)?,
127 doc.name,
128 )?,
129 min_width: ftd::Length::from(
130 ftd::p2::utils::string_optional("min-width", properties, doc.name, 0)?,
131 doc.name,
132 )?,
133 max_width: ftd::Length::from(
134 ftd::p2::utils::string_optional("max-width", properties, doc.name, 0)?,
135 doc.name,
136 )?,
137 height: ftd::Length::from(
138 ftd::p2::utils::string_optional("height", properties, doc.name, 0)?,
139 doc.name,
140 )?,
141 min_height: ftd::Length::from(
142 ftd::p2::utils::string_optional("min-height", properties, doc.name, 0)?,
143 doc.name,
144 )?,
145 max_height: ftd::Length::from(
146 ftd::p2::utils::string_optional("max-height", properties, doc.name, 0)?,
147 doc.name,
148 )?,
149 color: ftd::Color::from(
150 ftd::p2::utils::record_optional_with_ref("color", unresolved_properties, doc, 0)?,
151 doc,
152 0,
153 )?,
154 background_color: ftd::Color::from(
155 ftd::p2::utils::record_optional_with_ref(
156 "background-color",
157 unresolved_properties,
158 doc,
159 0,
160 )?,
161 doc,
162 0,
163 )?,
164 border_color: ftd::Color::from(
165 ftd::p2::utils::record_optional_with_ref(
166 "border-color",
167 unresolved_properties,
168 doc,
169 0,
170 )?,
171 doc,
172 0,
173 )?,
174 border_width: ftd::p2::utils::int_with_default("border-width", 0, properties, doc.name, 0)?,
175 border_radius: ftd::p2::utils::int_with_default(
176 "border-radius",
177 0,
178 properties,
179 doc.name,
180 0,
181 )?,
182 data_id: ftd::p2::utils::string_optional("id", properties, doc.name, 0)?.map(|v| {
183 if is_child {
184 v
185 } else {
186 format!("{}#{}", doc.name, v)
187 }
188 }),
189 id: None,
190 overflow_x: ftd::Overflow::from(
191 ftd::p2::utils::string_optional("overflow-x", properties, doc.name, 0)?,
192 doc.name,
193 )?,
194 overflow_y: ftd::Overflow::from(
195 ftd::p2::utils::string_optional("overflow-y", properties, doc.name, 0)?,
196 doc.name,
197 )?,
198 border_top: ftd::p2::utils::int_optional("border-top", properties, doc.name, 0)?,
199 border_left: ftd::p2::utils::int_optional("border-left", properties, doc.name, 0)?,
200 border_right: ftd::p2::utils::int_optional("border-right", properties, doc.name, 0)?,
201 border_bottom: ftd::p2::utils::int_optional("border-bottom", properties, doc.name, 0)?,
202 border_top_color: ftd::Color::from(
203 ftd::p2::utils::record_optional_with_ref(
204 "border-top-color",
205 unresolved_properties,
206 doc,
207 0,
208 )?,
209 doc,
210 0,
211 )?,
212 border_left_color: ftd::Color::from(
213 ftd::p2::utils::record_optional_with_ref(
214 "border-left-color",
215 unresolved_properties,
216 doc,
217 0,
218 )?,
219 doc,
220 0,
221 )?,
222 border_right_color: ftd::Color::from(
223 ftd::p2::utils::record_optional_with_ref(
224 "border-right-color",
225 unresolved_properties,
226 doc,
227 0,
228 )?,
229 doc,
230 0,
231 )?,
232 border_bottom_color: ftd::Color::from(
233 ftd::p2::utils::record_optional_with_ref(
234 "border-bottom-color",
235 unresolved_properties,
236 doc,
237 0,
238 )?,
239 doc,
240 0,
241 )?,
242 margin_top: ftd::p2::utils::int_optional("margin-top", properties, doc.name, 0)?,
243 margin_bottom: ftd::p2::utils::int_optional("margin-bottom", properties, doc.name, 0)?,
244 margin_left: ftd::p2::utils::int_optional("margin-left", properties, doc.name, 0)?,
245 margin_right: ftd::p2::utils::int_optional("margin-right", properties, doc.name, 0)?,
246 link,
247 open_in_new_tab: ftd::p2::utils::bool_with_default(
248 "open-in-new-tab",
249 false,
250 properties,
251 doc.name,
252 0,
253 )?,
254 sticky: ftd::p2::utils::bool_with_default("sticky", false, properties, doc.name, 0)?,
255 top: ftd::p2::utils::int_optional("top", properties, doc.name, 0)?,
256 bottom: ftd::p2::utils::int_optional("bottom", properties, doc.name, 0)?,
257 left: ftd::p2::utils::int_optional("left", properties, doc.name, 0)?,
258 right: ftd::p2::utils::int_optional("right", properties, doc.name, 0)?,
259 cursor: ftd::p2::utils::string_optional("cursor", properties, doc.name, 0)?,
260 submit,
261 shadow_offset_x: ftd::p2::utils::int_optional("shadow-offset-x", properties, doc.name, 0)?,
262 shadow_offset_y: ftd::p2::utils::int_optional("shadow-offset-y", properties, doc.name, 0)?,
263 shadow_size: ftd::p2::utils::int_optional("shadow-size", properties, doc.name, 0)?,
264 shadow_blur: ftd::p2::utils::int_optional("shadow-blur", properties, doc.name, 0)?,
265 shadow_color: ftd::Color::from(
266 ftd::p2::utils::record_optional_with_ref(
267 "shadow-color",
268 unresolved_properties,
269 doc,
270 0,
271 )?,
272 doc,
273 0,
274 )?,
275 gradient_direction: ftd::GradientDirection::from(
276 ftd::p2::utils::string_optional("gradient-direction", properties, doc.name, 0)?,
277 doc.name,
278 )?,
279 anchor,
280 gradient_colors,
281 background_image: {
282 let (src, reference) = ftd::p2::utils::record_optional_with_ref(
283 "background-image",
284 unresolved_properties,
285 doc,
286 0,
287 )?;
288 src.map_or(Ok(None), |r| {
289 ftd::ImageSrc::from(&r, doc, 0, reference).map(Some)
290 })?
291 },
292 background_repeat: ftd::p2::utils::bool_with_default(
293 "background-repeat",
294 false,
295 properties,
296 doc.name,
297 0,
298 )?,
299 background_parallax: ftd::p2::utils::bool_with_default(
300 "background-parallax",
301 false,
302 properties,
303 doc.name,
304 0,
305 )?,
306 scale: ftd::p2::utils::decimal_optional("scale", properties, doc.name, 0)?,
307 scale_x: ftd::p2::utils::decimal_optional("scale-x", properties, doc.name, 0)?,
308 scale_y: ftd::p2::utils::decimal_optional("scale-y", properties, doc.name, 0)?,
309 rotate: ftd::p2::utils::int_optional("rotate", properties, doc.name, 0)?,
310 move_up: ftd::p2::utils::int_optional("move-up", properties, doc.name, 0)?,
311 move_down: ftd::p2::utils::int_optional("move-down", properties, doc.name, 0)?,
312 move_left: ftd::p2::utils::int_optional("move-left", properties, doc.name, 0)?,
313 move_right: ftd::p2::utils::int_optional("move-right", properties, doc.name, 0)?,
314 position,
315 inner,
316 z_index: ftd::p2::utils::int_optional("z-index", properties, doc.name, 0)?,
317 slot: ftd::p2::utils::string_optional("slot", properties, doc.name, 0)?,
318 grid_column: ftd::p2::utils::string_optional("grid-column", properties, doc.name, 0)?,
319 grid_row: ftd::p2::utils::string_optional("grid-row", properties, doc.name, 0)?,
320 white_space: ftd::p2::utils::string_optional("white-space", properties, doc.name, 0)?,
321 border_style: ftd::p2::utils::string_optional("border-style", properties, doc.name, 0)?,
322 text_transform: ftd::p2::utils::string_optional("text-transform", properties, doc.name, 0)?,
323 })
324}
325
326fn common_arguments() -> Vec<(String, ftd::p2::Kind)> {
327 vec![
328 (
329 "padding".to_string(),
330 ftd::p2::Kind::integer().into_optional(),
331 ),
332 (
333 "padding-vertical".to_string(),
334 ftd::p2::Kind::integer().into_optional(),
335 ),
336 (
337 "padding-horizontal".to_string(),
338 ftd::p2::Kind::integer().into_optional(),
339 ),
340 (
341 "padding-left".to_string(),
342 ftd::p2::Kind::integer().into_optional(),
343 ),
344 (
345 "padding-right".to_string(),
346 ftd::p2::Kind::integer().into_optional(),
347 ),
348 (
349 "padding-top".to_string(),
350 ftd::p2::Kind::integer().into_optional(),
351 ),
352 (
353 "padding-bottom".to_string(),
354 ftd::p2::Kind::integer().into_optional(),
355 ),
356 (
357 "border-top-radius".to_string(),
358 ftd::p2::Kind::integer().into_optional(),
359 ),
360 (
361 "border-bottom-radius".to_string(),
362 ftd::p2::Kind::integer().into_optional(),
363 ),
364 (
365 "border-left-radius".to_string(),
366 ftd::p2::Kind::integer().into_optional(),
367 ),
368 (
369 "border-right-radius".to_string(),
370 ftd::p2::Kind::integer().into_optional(),
371 ),
372 ("width".to_string(), ftd::p2::Kind::string().into_optional()),
373 (
374 "min-width".to_string(),
375 ftd::p2::Kind::string().into_optional(),
376 ),
377 (
378 "max-width".to_string(),
379 ftd::p2::Kind::string().into_optional(),
380 ),
381 (
382 "height".to_string(),
383 ftd::p2::Kind::string().into_optional(),
384 ),
385 (
386 "min-height".to_string(),
387 ftd::p2::Kind::string().into_optional(),
388 ),
389 (
390 "max-height".to_string(),
391 ftd::p2::Kind::string().into_optional(),
392 ),
393 (
394 "explain".to_string(),
396 ftd::p2::Kind::boolean().into_optional(),
397 ),
398 (
399 "region".to_string(),
400 ftd::p2::Kind::string().into_optional(),
401 ),
402 (
403 "color".to_string(),
404 ftd::p2::Kind::Record {
405 name: "ftd#color".to_string(),
406 default: None,
407 is_reference: false,
408 }
409 .into_optional(),
410 ),
411 (
412 "background-color".to_string(),
413 ftd::p2::Kind::Record {
414 name: "ftd#color".to_string(),
415 default: None,
416 is_reference: false,
417 }
418 .into_optional(),
419 ),
420 (
421 "border-color".to_string(),
422 ftd::p2::Kind::Record {
423 name: "ftd#color".to_string(),
424 default: None,
425 is_reference: false,
426 }
427 .into_optional(),
428 ),
429 (
430 "border-width".to_string(),
431 ftd::p2::Kind::integer().into_optional(),
432 ),
433 (
434 "border-radius".to_string(),
435 ftd::p2::Kind::integer().into_optional(),
436 ),
437 ("id".to_string(), ftd::p2::Kind::string().into_optional()),
438 (
439 "overflow-x".to_string(),
440 ftd::p2::Kind::string().into_optional(),
441 ),
442 (
443 "overflow-y".to_string(),
444 ftd::p2::Kind::string().into_optional(),
445 ),
446 (
447 "border-top".to_string(),
448 ftd::p2::Kind::integer().into_optional(),
449 ),
450 (
451 "border-bottom".to_string(),
452 ftd::p2::Kind::integer().into_optional(),
453 ),
454 (
455 "border-left".to_string(),
456 ftd::p2::Kind::integer().into_optional(),
457 ),
458 (
459 "border-right".to_string(),
460 ftd::p2::Kind::integer().into_optional(),
461 ),
462 (
463 "border-top-color".to_string(),
464 ftd::p2::Kind::record("ftd#color").into_optional(),
465 ),
466 (
467 "border-left-color".to_string(),
468 ftd::p2::Kind::record("ftd#color").into_optional(),
469 ),
470 (
471 "border-right-color".to_string(),
472 ftd::p2::Kind::record("ftd#color").into_optional(),
473 ),
474 (
475 "border-bottom-color".to_string(),
476 ftd::p2::Kind::record("ftd#color").into_optional(),
477 ),
478 (
479 "margin-top".to_string(),
480 ftd::p2::Kind::integer().into_optional(),
481 ),
482 (
483 "margin-bottom".to_string(),
484 ftd::p2::Kind::integer().into_optional(),
485 ),
486 (
487 "margin-left".to_string(),
488 ftd::p2::Kind::integer().into_optional(),
489 ),
490 (
491 "margin-right".to_string(),
492 ftd::p2::Kind::integer().into_optional(),
493 ),
494 ("link".to_string(), ftd::p2::Kind::string().into_optional()),
495 (
496 "submit".to_string(),
497 ftd::p2::Kind::string().into_optional(),
498 ),
499 (
500 "open-in-new-tab".to_string(),
501 ftd::p2::Kind::boolean().into_optional(),
502 ),
503 (
504 "sticky".to_string(),
505 ftd::p2::Kind::boolean().into_optional(),
506 ),
507 ("top".to_string(), ftd::p2::Kind::integer().into_optional()),
508 (
509 "bottom".to_string(),
510 ftd::p2::Kind::integer().into_optional(),
511 ),
512 ("left".to_string(), ftd::p2::Kind::integer().into_optional()),
513 (
514 "right".to_string(),
515 ftd::p2::Kind::integer().into_optional(),
516 ),
517 (
518 "cursor".to_string(),
519 ftd::p2::Kind::string().into_optional(),
520 ),
521 (
522 "anchor".to_string(),
523 ftd::p2::Kind::string().into_optional(),
524 ),
525 (
526 "gradient-direction".to_string(),
527 ftd::p2::Kind::string().into_optional(),
528 ),
529 (
530 "gradient-colors".to_string(),
531 ftd::p2::Kind::string().into_optional(),
532 ),
533 (
534 "shadow-offset-x".to_string(),
535 ftd::p2::Kind::integer().into_optional(),
536 ),
537 (
538 "shadow-offset-y".to_string(),
539 ftd::p2::Kind::integer().into_optional(),
540 ),
541 (
542 "shadow-blur".to_string(),
543 ftd::p2::Kind::integer().into_optional(),
544 ),
545 (
546 "shadow-size".to_string(),
547 ftd::p2::Kind::integer().into_optional(),
548 ),
549 (
550 "shadow-color".to_string(),
551 ftd::p2::Kind::record("ftd#color").into_optional(),
552 ),
553 (
554 "background-image".to_string(),
555 ftd::p2::Kind::record("ftd#image-src").into_optional(),
556 ),
557 (
558 "background-repeat".to_string(),
559 ftd::p2::Kind::boolean().into_optional(),
560 ),
561 (
562 "background-parallax".to_string(),
563 ftd::p2::Kind::boolean().into_optional(),
564 ),
565 (
566 "scale".to_string(),
567 ftd::p2::Kind::decimal().into_optional(),
568 ),
569 (
570 "scale-x".to_string(),
571 ftd::p2::Kind::decimal().into_optional(),
572 ),
573 (
574 "scale-y".to_string(),
575 ftd::p2::Kind::decimal().into_optional(),
576 ),
577 (
578 "rotate".to_string(),
579 ftd::p2::Kind::integer().into_optional(),
580 ),
581 (
582 "move-up".to_string(),
583 ftd::p2::Kind::integer().into_optional(),
584 ),
585 (
586 "move-down".to_string(),
587 ftd::p2::Kind::integer().into_optional(),
588 ),
589 (
590 "move-left".to_string(),
591 ftd::p2::Kind::integer().into_optional(),
592 ),
593 (
594 "move-right".to_string(),
595 ftd::p2::Kind::integer().into_optional(),
596 ),
597 (
598 "position".to_string(),
599 ftd::p2::Kind::string().into_optional(),
600 ),
601 (
602 "z-index".to_string(),
603 ftd::p2::Kind::integer().into_optional(),
604 ),
605 ("slot".to_string(), ftd::p2::Kind::string().into_optional()),
606 (
607 "white-space".to_string(),
608 ftd::p2::Kind::string().into_optional(),
609 ),
610 (
611 "border-style".to_string(),
612 ftd::p2::Kind::string().into_optional(),
613 ),
614 (
615 "text-transform".to_string(),
616 ftd::p2::Kind::string().into_optional(),
617 ),
618 ]
627}
628
629pub fn null() -> ftd::Component {
630 ftd::Component {
631 kernel: true,
632 full_name: "ftd#null".to_string(),
633 root: "ftd.kernel".to_string(),
634 ..Default::default()
635 }
636}
637
638pub fn container_from_properties(
639 properties: &ftd::Map<ftd::Value>,
640 doc: &ftd::p2::TDoc,
641) -> ftd::p1::Result<ftd::Container> {
642 Ok(ftd::Container {
643 children: Default::default(),
644 external_children: Default::default(),
645 open: ftd::p2::utils::bool_optional("open", properties, doc.name, 0)?,
646 append_at: ftd::p2::utils::string_optional("append-at", properties, doc.name, 0)?,
647 wrap: ftd::p2::utils::bool_with_default("wrap", false, properties, doc.name, 0)?,
648 })
649}
650
651fn container_arguments() -> Vec<(String, ftd::p2::Kind)> {
652 vec![
653 ("open".to_string(), ftd::p2::Kind::boolean().into_optional()),
654 (
655 "append-at".to_string(),
656 ftd::p2::Kind::string().into_optional(),
657 ),
658 ("align".to_string(), ftd::p2::Kind::string().into_optional()),
659 ("wrap".to_string(), ftd::p2::Kind::boolean().into_optional()),
660 ]
661}
662
663pub fn image_function() -> ftd::Component {
664 ftd::Component {
665 kernel: true,
666 full_name: "ftd#image".to_string(),
667 root: "ftd.kernel".to_string(),
668 arguments: [
669 vec![
670 ("src".to_string(), ftd::p2::Kind::record("ftd#image-src")),
671 (
672 "description".to_string(),
673 ftd::p2::Kind::string().into_optional(),
674 ),
675 ("title".to_string(), ftd::p2::Kind::string().into_optional()),
676 ("align".to_string(), ftd::p2::Kind::string().into_optional()),
677 ("crop".to_string(), ftd::p2::Kind::boolean().into_optional()),
678 (
679 "loading".to_string(),
680 ftd::p2::Kind::string().into_optional(),
681 ),
682 ],
683 common_arguments(),
684 ]
685 .concat()
686 .into_iter()
687 .collect(),
688 locals: Default::default(),
689 properties: Default::default(),
690 instructions: Default::default(),
691 invocations: Default::default(),
692 condition: None,
693 events: vec![],
694 line_number: 0,
695 }
696}
697
698pub fn image_from_properties(
699 unresolved_properties: &ftd::Map<ftd::component::Property>,
700 doc: &ftd::p2::TDoc,
701 condition: &Option<ftd::p2::Boolean>,
702 is_child: bool,
703 events: &[ftd::p2::Event],
704) -> ftd::p1::Result<ftd::Image> {
705 let (src, reference) =
706 ftd::p2::utils::record_and_ref(0, "src", unresolved_properties, doc, condition)?;
707 let src_record = ftd::ImageSrc::from(&src, doc, 0, reference.clone())?;
708 let properties = &ftd::component::resolve_properties(0, unresolved_properties, doc)?;
709 Ok(ftd::Image {
710 src: src_record,
711 description: ftd::p2::utils::string_optional("description", properties, doc.name, 0)?,
712 common: common_from_properties(
713 unresolved_properties,
714 doc,
715 condition,
716 is_child,
717 events,
718 reference,
719 )?,
720 loading: ftd::Loading::from(
721 ftd::p2::utils::string_with_default("loading", "lazy", properties, doc.name, 0)?
722 .as_str(),
723 doc.name,
724 )?,
725 crop: ftd::p2::utils::bool_with_default("crop", false, properties, doc.name, 0)?,
726 })
727}
728
729pub fn row_function() -> ftd::Component {
730 ftd::Component {
731 kernel: true,
732 full_name: "ftd#row".to_string(),
733 root: "ftd.kernel".to_string(),
734 arguments: [
735 container_arguments(),
736 common_arguments(),
737 vec![(
738 "spacing".to_string(),
739 ftd::p2::Kind::string().into_optional(),
740 )],
741 ]
742 .concat()
743 .into_iter()
744 .collect(),
745 locals: Default::default(),
746 properties: Default::default(),
747 instructions: Default::default(),
748 invocations: Default::default(),
749 condition: None,
750 events: vec![],
751 line_number: 0,
752 }
753}
754
755pub fn row_from_properties(
756 unresolved_properties: &ftd::Map<ftd::component::Property>,
757 doc: &ftd::p2::TDoc,
758 condition: &Option<ftd::p2::Boolean>,
759 is_child: bool,
760 events: &[ftd::p2::Event],
761) -> ftd::p1::Result<ftd::Row> {
762 let properties = &ftd::component::resolve_properties(0, unresolved_properties, doc)?;
763 Ok(ftd::Row {
764 common: common_from_properties(
765 unresolved_properties,
766 doc,
767 condition,
768 is_child,
769 events,
770 None,
771 )?,
772 container: container_from_properties(properties, doc)?,
773 spacing: ftd::Spacing::from(ftd::p2::utils::string_optional(
774 "spacing", properties, doc.name, 0,
775 )?)?,
776 })
777}
778
779pub fn column_function() -> ftd::Component {
780 ftd::Component {
781 line_number: 0,
782 kernel: true,
783 full_name: "ftd#column".to_string(),
784 root: "ftd.kernel".to_string(),
785 arguments: [
786 container_arguments(),
787 common_arguments(),
788 vec![(
789 "spacing".to_string(),
790 ftd::p2::Kind::string().into_optional(),
791 )],
792 ]
793 .concat()
794 .into_iter()
795 .collect(),
796 locals: Default::default(),
797 properties: Default::default(),
798 instructions: Default::default(),
799 invocations: Default::default(),
800 condition: None,
801 events: vec![],
802 }
803}
804
805pub fn column_from_properties(
806 unresolved_properties: &ftd::Map<ftd::component::Property>,
807 doc: &ftd::p2::TDoc,
808 condition: &Option<ftd::p2::Boolean>,
809 is_child: bool,
810 events: &[ftd::p2::Event],
811) -> ftd::p1::Result<ftd::Column> {
812 let properties = &ftd::component::resolve_properties(0, unresolved_properties, doc)?;
813 Ok(ftd::Column {
814 common: common_from_properties(
815 unresolved_properties,
816 doc,
817 condition,
818 is_child,
819 events,
820 None,
821 )?,
822 container: container_from_properties(properties, doc)?,
823 spacing: ftd::Spacing::from(ftd::p2::utils::string_optional(
824 "spacing", properties, doc.name, 0,
825 )?)?,
826 })
827}
828
829#[allow(dead_code)]
830#[allow(unused_variables)]
831pub fn text_render(
832 tf: &ftd::TextFormat,
833 text: String,
834 source: ftd::TextSource,
835 theme: String,
836 doc_id: &str,
837) -> ftd::p1::Result<ftd::Rendered> {
838 Ok(match (source, tf) {
839 (ftd::TextSource::Body, ftd::TextFormat::Markdown) => ftd::rendered::markup(text.as_str()),
840 (_, ftd::TextFormat::Markdown) => ftd::rendered::markup_line(text.as_str()),
841 (_, ftd::TextFormat::Code { lang }) => {
842 ftd::rendered::code_with_theme(text.as_str(), lang.as_str(), theme.as_str(), doc_id)?
843 }
844 (_, ftd::TextFormat::Text) => ftd::Rendered {
845 original: text.clone(),
846 rendered: text,
847 },
848 })
849}
850
851pub fn iframe_function() -> ftd::Component {
852 ftd::Component {
853 line_number: 0,
854 kernel: true,
855 root: "ftd.kernel".to_string(),
856 full_name: "ftd#iframe".to_string(),
857 arguments: [
858 vec![
859 ("src".to_string(), ftd::p2::Kind::string().into_optional()),
860 (
861 "youtube".to_string(),
862 ftd::p2::Kind::string().into_optional(),
863 ),
864 (
865 "loading".to_string(),
866 ftd::p2::Kind::string().into_optional(),
867 ),
868 ],
869 common_arguments(),
870 ]
871 .concat()
872 .into_iter()
873 .collect(),
874 locals: Default::default(),
875 properties: Default::default(),
876 instructions: Default::default(),
877 invocations: Default::default(),
878 condition: None,
879 events: vec![],
880 }
881}
882
883pub fn iframe_from_properties(
884 unresolved_properties: &ftd::Map<ftd::component::Property>,
885 doc: &ftd::p2::TDoc,
886 condition: &Option<ftd::p2::Boolean>,
887 is_child: bool,
888 events: &[ftd::p2::Event],
889) -> ftd::p1::Result<ftd::IFrame> {
890 let properties = &ftd::component::resolve_properties(0, unresolved_properties, doc)?;
891 let src = match (
892 ftd::p2::utils::string_optional("src", properties, doc.name, 0)?,
893 ftd::p2::utils::string_optional("youtube", properties, doc.name, 0)?
894 .and_then(|id| ftd::youtube_id::from_raw(id.as_str())),
895 ) {
896 (Some(src), None) => src,
897 (None, Some(id)) => id,
898 (Some(_), Some(_)) => {
899 return ftd::p2::utils::e2("both src and youtube id provided", doc.name, 0)
900 }
901 (None, None) => return ftd::p2::utils::e2("src or youtube id is required", doc.name, 0),
902 };
903
904 Ok(ftd::IFrame {
905 src,
906 loading: ftd::Loading::from(
907 ftd::p2::utils::string_with_default("loading", "lazy", properties, doc.name, 0)?
908 .as_str(),
909 doc.name,
910 )?,
911 common: common_from_properties(
912 unresolved_properties,
913 doc,
914 condition,
915 is_child,
916 events,
917 None,
918 )?,
919 })
920}
921
922pub fn text_block_from_properties(
923 unresolved_properties: &ftd::Map<ftd::component::Property>,
924 doc: &ftd::p2::TDoc,
925 condition: &Option<ftd::p2::Boolean>,
926 is_child: bool,
927 events: &[ftd::p2::Event],
928) -> ftd::p1::Result<ftd::TextBlock> {
929 let (text, source, reference) = ftd::p2::utils::string_and_source_and_ref(
930 0,
931 "text",
932 unresolved_properties,
933 doc,
934 condition,
935 )?;
936 let properties = &ftd::component::resolve_properties(0, unresolved_properties, doc)?;
937 let font_str = ftd::p2::utils::string_optional("role", properties, doc.name, 0)?;
938
939 let font: Vec<ftd::NamedFont> = match font_str {
940 Some(f) => f
941 .split(',')
942 .flat_map(|x| ftd::NamedFont::from(Some(x.to_string())))
943 .collect(),
944 None => vec![],
945 };
946 Ok(ftd::TextBlock {
947 line: source != ftd::TextSource::Body,
948 text: if source == ftd::TextSource::Body {
949 ftd::rendered::markup(text.as_str())
950 } else {
951 ftd::rendered::markup_line(text.as_str())
952 },
953 common: common_from_properties(
954 unresolved_properties,
955 doc,
956 condition,
957 is_child,
958 events,
959 reference,
960 )?,
961 text_align: ftd::TextAlign::from(
962 ftd::p2::utils::string_optional("text-align", properties, doc.name, 0)?,
963 doc.name,
964 )?,
965 style: ftd::Style::from(
966 ftd::p2::utils::string_optional("style", properties, doc.name, 0)?,
967 doc.name,
968 )?,
969 size: ftd::p2::utils::int_optional("size", properties, doc.name, 0)?,
970 font,
971 line_height: ftd::p2::utils::int_optional("line-height", properties, doc.name, 0)?,
972 line_clamp: ftd::p2::utils::int_optional("line-clamp", properties, doc.name, 0)?,
973 text_indent: ftd::Length::from(
974 ftd::p2::utils::string_optional("text-indent", properties, doc.name, 0)?,
975 doc.name,
976 )?,
977 })
978}
979
980pub fn code_from_properties(
981 unresolved_properties: &ftd::Map<ftd::component::Property>,
982 doc: &ftd::p2::TDoc,
983 condition: &Option<ftd::p2::Boolean>,
984 is_child: bool,
985 events: &[ftd::p2::Event],
986) -> ftd::p1::Result<ftd::Code> {
987 let (text, _, reference) = ftd::p2::utils::string_and_source_and_ref(
988 0,
989 "text",
990 unresolved_properties,
991 doc,
992 condition,
993 )?;
994 let properties = &ftd::component::resolve_properties(0, unresolved_properties, doc)?;
995 let font_str = ftd::p2::utils::record_optional("role", properties, doc.name, 0)?;
996 let mut font_reference = None;
997 if font_str.is_some() {
998 font_reference =
999 ftd::p2::utils::record_and_ref(0, "role", unresolved_properties, doc, condition)?.1;
1000 }
1001 let font = font_str.map_or(Ok(None), |v| {
1002 ftd::Type::from(&v, doc, 0, font_reference).map(Some)
1003 })?;
1004
1005 Ok(ftd::Code {
1006 text: ftd::rendered::code_with_theme(
1007 text.as_str(),
1008 ftd::p2::utils::string_optional("lang", properties, doc.name, 0)?
1009 .unwrap_or_else(|| "txt".to_string())
1010 .as_str(),
1011 ftd::p2::utils::string_with_default(
1012 "theme",
1013 ftd::code::DEFAULT_THEME,
1014 properties,
1015 doc.name,
1016 0,
1017 )?
1018 .as_str(),
1019 doc.name,
1020 )?,
1021 common: common_from_properties(
1022 unresolved_properties,
1023 doc,
1024 condition,
1025 is_child,
1026 events,
1027 reference,
1028 )?,
1029 text_align: ftd::TextAlign::from(
1030 ftd::p2::utils::string_optional("text-align", properties, doc.name, 0)?,
1031 doc.name,
1032 )?,
1033 style: ftd::Style::from(
1034 ftd::p2::utils::string_optional("style", properties, doc.name, 0)?,
1035 doc.name,
1036 )?,
1037 font,
1038 line_clamp: ftd::p2::utils::int_optional("line-clamp", properties, doc.name, 0)?,
1039 text_indent: ftd::Length::from(
1040 ftd::p2::utils::string_optional("text-indent", properties, doc.name, 0)?,
1041 doc.name,
1042 )?,
1043 })
1044}
1045
1046pub fn integer_from_properties(
1047 unresolved_properties: &ftd::Map<ftd::component::Property>,
1048 doc: &ftd::p2::TDoc,
1049 condition: &Option<ftd::p2::Boolean>,
1050 is_child: bool,
1051 events: &[ftd::p2::Event],
1052) -> ftd::p1::Result<ftd::Text> {
1053 let reference =
1054 ftd::p2::utils::integer_and_ref(0, "value", unresolved_properties, doc, condition)?.1;
1055 let properties = &ftd::component::resolve_properties(0, unresolved_properties, doc)?;
1056 let num = format_num::NumberFormat::new();
1057 let text = match ftd::p2::utils::string_optional("format", properties, doc.name, 0)? {
1058 Some(f) => num.format(
1059 f.as_str(),
1060 ftd::p2::utils::int("value", properties, doc.name, 0)? as f64,
1061 ),
1062 None => ftd::p2::utils::int("value", properties, doc.name, 0)?.to_string(),
1063 };
1064
1065 let font_str = ftd::p2::utils::record_optional("role", properties, doc.name, 0)?;
1066 let mut font_reference = None;
1067 if font_str.is_some() {
1068 font_reference =
1069 ftd::p2::utils::record_and_ref(0, "role", unresolved_properties, doc, condition)?.1;
1070 }
1071 let font = font_str.map_or(Ok(None), |v| {
1072 ftd::Type::from(&v, doc, 0, font_reference).map(Some)
1073 })?;
1074
1075 Ok(ftd::Text {
1076 text: ftd::rendered::markup_line(text.as_str()),
1077 line: false,
1078 common: common_from_properties(
1079 unresolved_properties,
1080 doc,
1081 condition,
1082 is_child,
1083 events,
1084 reference,
1085 )?,
1086 text_align: ftd::TextAlign::from(
1087 ftd::p2::utils::string_optional("text-align", properties, doc.name, 0)?,
1088 doc.name,
1089 )?,
1090 style: ftd::Style::from(
1091 ftd::p2::utils::string_optional("style", properties, doc.name, 0)?,
1092 doc.name,
1093 )?,
1094 font,
1095 line_clamp: ftd::p2::utils::int_optional("line-clamp", properties, doc.name, 0)?,
1096 text_indent: ftd::Length::from(
1097 ftd::p2::utils::string_optional("text-indent", properties, doc.name, 0)?,
1098 doc.name,
1099 )?,
1100 })
1101}
1102
1103pub fn decimal_from_properties(
1104 unresolved_properties: &ftd::Map<ftd::component::Property>,
1105 doc: &ftd::p2::TDoc,
1106 condition: &Option<ftd::p2::Boolean>,
1107 is_child: bool,
1108 events: &[ftd::p2::Event],
1109) -> ftd::p1::Result<ftd::Text> {
1110 let reference =
1111 ftd::p2::utils::decimal_and_ref(0, "value", unresolved_properties, doc, condition)?.1;
1112 let properties = &ftd::component::resolve_properties(0, unresolved_properties, doc)?;
1113 let num = format_num::NumberFormat::new();
1114 let text = match ftd::p2::utils::string_optional("format", properties, doc.name, 0)? {
1115 Some(f) => num.format(
1116 f.as_str(),
1117 ftd::p2::utils::decimal("value", properties, doc.name, 0)?,
1118 ),
1119 None => ftd::p2::utils::decimal("value", properties, doc.name, 0)?.to_string(),
1120 };
1121
1122 let font_str = ftd::p2::utils::record_optional("role", properties, doc.name, 0)?;
1123 let mut font_reference = None;
1124 if font_str.is_some() {
1125 font_reference =
1126 ftd::p2::utils::record_and_ref(0, "role", unresolved_properties, doc, condition)?.1;
1127 }
1128 let font = font_str.map_or(Ok(None), |v| {
1129 ftd::Type::from(&v, doc, 0, font_reference).map(Some)
1130 })?;
1131 Ok(ftd::Text {
1132 text: ftd::rendered::markup_line(text.as_str()),
1133 line: false,
1134 common: common_from_properties(
1135 unresolved_properties,
1136 doc,
1137 condition,
1138 is_child,
1139 events,
1140 reference,
1141 )?,
1142 text_align: ftd::TextAlign::from(
1143 ftd::p2::utils::string_optional("text-align", properties, doc.name, 0)?,
1144 doc.name,
1145 )?,
1146 style: ftd::Style::from(
1147 ftd::p2::utils::string_optional("style", properties, doc.name, 0)?,
1148 doc.name,
1149 )?,
1150 font,
1151 line_clamp: ftd::p2::utils::int_optional("line-clamp", properties, doc.name, 0)?,
1152 text_indent: ftd::Length::from(
1153 ftd::p2::utils::string_optional("text-indent", properties, doc.name, 0)?,
1154 doc.name,
1155 )?,
1156 })
1157}
1158
1159pub fn color_from(l: Option<String>, doc_id: &str) -> ftd::p1::Result<Option<ftd::ColorValue>> {
1160 use std::str::FromStr;
1161
1162 let v = match l {
1163 Some(v) => v,
1164 None => return Ok(None),
1165 };
1166
1167 let v = v.trim().to_string();
1168
1169 let mut string = v.replace(' ', "");
1171 string.make_ascii_lowercase();
1172 if v.starts_with('#') && v.len() == 9 {
1173 let (_, value_string) = string.split_at(1);
1174
1175 let iv = u64::from_str_radix(value_string, 16).map_err(|e| ftd::p1::Error::ParseError {
1176 message: e.to_string(),
1177 doc_id: doc_id.to_string(),
1178 line_number: 0,
1179 })?;
1180
1181 if iv > 0xffffffff {
1183 return ftd::p2::utils::e2(format!("{} is not a valid color", v), doc_id, 0);
1184 }
1185
1186 Ok(Some(ftd::ColorValue {
1188 r: ((iv & 0xff000000) >> 24) as u8,
1189 g: ((iv & 0xff0000) >> 16) as u8,
1190 b: ((iv & 0xff00) >> 8) as u8,
1191 alpha: round_1p((iv & 0xff) as f32 / 255_f32) as f32,
1192 }))
1193 } else {
1194 match css_color_parser::Color::from_str(v.as_str()) {
1195 Ok(v) => Ok(Some(ftd::ColorValue {
1196 r: v.r,
1197 g: v.g,
1198 b: v.b,
1199 alpha: v.a,
1200 })),
1201 Err(e) => ftd::p2::utils::e2(format!("{} is not a valid color: {:?}", v, e), doc_id, 0),
1202 }
1203 }
1204}
1205fn round_1p(n: f32) -> f32 {
1206 let temp = (n * 10_f32) as u32;
1208 let last = (temp % 10) as f32;
1209 let front = n as u32;
1210
1211 front as f32 + last / 10_f32
1212}
1213
1214pub fn boolean_from_properties(
1215 unresolved_properties: &ftd::Map<ftd::component::Property>,
1216 doc: &ftd::p2::TDoc,
1217 condition: &Option<ftd::p2::Boolean>,
1218 is_child: bool,
1219 events: &[ftd::p2::Event],
1220) -> ftd::p1::Result<ftd::Text> {
1221 let reference =
1222 ftd::p2::utils::boolean_and_ref(0, "value", unresolved_properties, doc, condition)?.1;
1223 let properties = &ftd::component::resolve_properties(0, unresolved_properties, doc)?;
1224 let value = ftd::p2::utils::bool_("value", properties, doc.name, 0)?;
1225 let text = if value {
1226 ftd::p2::utils::string_with_default("true", "true", properties, doc.name, 0)?
1227 } else {
1228 ftd::p2::utils::string_with_default("false", "false", properties, doc.name, 0)?
1229 };
1230
1231 let font_str = ftd::p2::utils::record_optional("role", properties, doc.name, 0)?;
1232 let mut font_reference = None;
1233 if font_str.is_some() {
1234 font_reference =
1235 ftd::p2::utils::record_and_ref(0, "role", unresolved_properties, doc, condition)?.1;
1236 }
1237 let font = font_str.map_or(Ok(None), |v| {
1238 ftd::Type::from(&v, doc, 0, font_reference).map(Some)
1239 })?;
1240
1241 Ok(ftd::Text {
1242 text: ftd::rendered::markup_line(text.as_str()),
1243 line: false,
1244 common: common_from_properties(
1245 unresolved_properties,
1246 doc,
1247 condition,
1248 is_child,
1249 events,
1250 reference,
1251 )?,
1252 text_align: ftd::TextAlign::from(
1253 ftd::p2::utils::string_optional("text-align", properties, doc.name, 0)?,
1254 doc.name,
1255 )?,
1256 style: ftd::Style::from(
1257 ftd::p2::utils::string_optional("style", properties, doc.name, 0)?,
1258 doc.name,
1259 )?,
1260 font,
1261 line_clamp: ftd::p2::utils::int_optional("line-clamp", properties, doc.name, 0)?,
1262 text_indent: ftd::Length::from(
1263 ftd::p2::utils::string_optional("text-indent", properties, doc.name, 0)?,
1264 doc.name,
1265 )?,
1266 })
1267}
1268
1269pub fn text_function() -> ftd::Component {
1270 ftd::Component {
1271 line_number: 0,
1272 kernel: true,
1273 root: "ftd.kernel".to_string(),
1274 full_name: "ftd#text-block".to_string(),
1275 arguments: [
1276 vec![
1277 ("text".to_string(), ftd::p2::Kind::caption_or_body()),
1278 ("align".to_string(), ftd::p2::Kind::string().into_optional()),
1279 ("style".to_string(), ftd::p2::Kind::string().into_optional()),
1280 (
1281 "role".to_string(),
1282 ftd::p2::Kind::record("ftd#type").into_optional(),
1283 ),
1284 (
1285 "line-clamp".to_string(),
1286 ftd::p2::Kind::integer().into_optional(),
1287 ),
1288 (
1289 "text-indent".to_string(),
1290 ftd::p2::Kind::integer().into_optional(),
1291 ),
1292 (
1293 "text-align".to_string(),
1294 ftd::p2::Kind::string().into_optional(),
1295 ),
1296 ],
1297 common_arguments(),
1298 ]
1299 .concat()
1300 .into_iter()
1301 .collect(),
1302 locals: Default::default(),
1303 properties: Default::default(),
1304 instructions: Default::default(),
1305 invocations: Default::default(),
1306 condition: None,
1307 events: vec![],
1308 }
1309}
1310
1311pub fn code_function() -> ftd::Component {
1312 ftd::Component {
1313 line_number: 0,
1314 kernel: true,
1315 root: "ftd.kernel".to_string(),
1316 full_name: "ftd#code".to_string(),
1317 arguments: [
1318 vec![
1319 ("text".to_string(), ftd::p2::Kind::caption_or_body()),
1320 ("align".to_string(), ftd::p2::Kind::string().into_optional()),
1321 ("style".to_string(), ftd::p2::Kind::string().into_optional()),
1322 ("lang".to_string(), ftd::p2::Kind::string().into_optional()),
1323 ("theme".to_string(), ftd::p2::Kind::string().into_optional()),
1324 (
1325 "role".to_string(),
1326 ftd::p2::Kind::record("ftd#type").into_optional(),
1327 ),
1328 (
1329 "line-clamp".to_string(),
1330 ftd::p2::Kind::integer().into_optional(),
1331 ),
1332 (
1333 "text-indent".to_string(),
1334 ftd::p2::Kind::string().into_optional(),
1335 ),
1336 (
1337 "text-align".to_string(),
1338 ftd::p2::Kind::string().into_optional(),
1339 ),
1340 ],
1341 common_arguments(),
1342 ]
1343 .concat()
1344 .into_iter()
1345 .collect(),
1346 locals: Default::default(),
1347 properties: Default::default(),
1348 instructions: Default::default(),
1349 invocations: Default::default(),
1350 condition: None,
1351 events: vec![],
1352 }
1353}
1354
1355pub fn integer_function() -> ftd::Component {
1356 ftd::Component {
1357 line_number: 0,
1358 kernel: true,
1359 root: "ftd.kernel".to_string(),
1360 full_name: "ftd#integer".to_string(),
1361 arguments: [
1362 vec![
1363 ("value".to_string(), ftd::p2::Kind::integer()),
1364 ("align".to_string(), ftd::p2::Kind::string().into_optional()),
1365 ("style".to_string(), ftd::p2::Kind::string().into_optional()),
1366 (
1367 "format".to_string(),
1368 ftd::p2::Kind::string().into_optional(),
1369 ),
1370 (
1371 "role".to_string(),
1372 ftd::p2::Kind::record("ftd#type").into_optional(),
1373 ),
1374 (
1375 "text-align".to_string(),
1376 ftd::p2::Kind::string().into_optional(),
1377 ),
1378 ],
1379 common_arguments(),
1380 ]
1381 .concat()
1382 .into_iter()
1383 .collect(),
1384 locals: Default::default(),
1385 properties: Default::default(),
1386 instructions: Default::default(),
1387 invocations: Default::default(),
1388 condition: None,
1389 events: vec![],
1390 }
1391}
1392
1393pub fn decimal_function() -> ftd::Component {
1394 ftd::Component {
1395 line_number: 0,
1396 kernel: true,
1397 root: "ftd.kernel".to_string(),
1398 full_name: "ftd#decimal".to_string(),
1399 arguments: [
1400 vec![
1401 ("value".to_string(), ftd::p2::Kind::decimal()),
1402 ("align".to_string(), ftd::p2::Kind::string().into_optional()),
1403 ("style".to_string(), ftd::p2::Kind::string().into_optional()),
1404 (
1405 "format".to_string(),
1406 ftd::p2::Kind::string().into_optional(),
1407 ),
1408 (
1409 "role".to_string(),
1410 ftd::p2::Kind::record("ftd#type").into_optional(),
1411 ),
1412 (
1413 "text-align".to_string(),
1414 ftd::p2::Kind::string().into_optional(),
1415 ),
1416 ],
1417 common_arguments(),
1418 ]
1419 .concat()
1420 .into_iter()
1421 .collect(),
1422 locals: Default::default(),
1423 properties: Default::default(),
1424 instructions: Default::default(),
1425 invocations: Default::default(),
1426 condition: None,
1427 events: vec![],
1428 }
1429}
1430
1431pub fn scene_function() -> ftd::Component {
1432 let arguments = {
1433 let mut arguments: ftd::Map<ftd::p2::Kind> = [
1434 container_arguments(),
1435 common_arguments(),
1436 vec![(
1437 "spacing".to_string(),
1438 ftd::p2::Kind::string().into_optional(),
1439 )],
1440 ]
1441 .concat()
1442 .into_iter()
1443 .collect();
1444 arguments.remove("spacing");
1445 arguments.remove("wrap");
1446 arguments
1447 };
1448
1449 ftd::Component {
1450 line_number: 0,
1451 kernel: true,
1452 root: "ftd.kernel".to_string(),
1453 full_name: "ftd#scene".to_string(),
1454 arguments,
1455 locals: Default::default(),
1456 properties: Default::default(),
1457 instructions: Default::default(),
1458 invocations: Default::default(),
1459 condition: None,
1460 events: vec![],
1461 }
1462}
1463
1464pub fn markup_function() -> ftd::Component {
1465 ftd::Component {
1466 line_number: 0,
1467 kernel: true,
1468 root: "ftd.kernel".to_string(),
1469 full_name: "ftd#text".to_string(),
1470 arguments: [
1471 vec![
1472 ("text".to_string(), ftd::p2::Kind::caption_or_body()),
1473 ("align".to_string(), ftd::p2::Kind::string().into_optional()),
1474 ("style".to_string(), ftd::p2::Kind::string().into_optional()),
1475 (
1476 "role".to_string(),
1477 ftd::p2::Kind::record("ftd#type").into_optional(),
1478 ),
1479 (
1480 "line-clamp".to_string(),
1481 ftd::p2::Kind::integer().into_optional(),
1482 ),
1483 (
1484 "text-indent".to_string(),
1485 ftd::p2::Kind::string().into_optional(),
1486 ),
1487 (
1488 "text-align".to_string(),
1489 ftd::p2::Kind::string().into_optional(),
1490 ),
1491 ],
1492 common_arguments(),
1493 ]
1494 .concat()
1495 .into_iter()
1496 .collect(),
1497 locals: Default::default(),
1498 properties: Default::default(),
1499 instructions: Default::default(),
1500 invocations: Default::default(),
1501 condition: None,
1502 events: vec![],
1503 }
1504}
1505
1506pub fn grid_function() -> ftd::Component {
1507 let arguments: ftd::Map<ftd::p2::Kind> = [
1508 container_arguments(),
1509 common_arguments(),
1510 vec![
1511 ("slots".to_string(), ftd::p2::Kind::string()),
1512 (
1513 "slot-widths".to_string(),
1514 ftd::p2::Kind::string().into_optional(),
1515 ),
1516 (
1517 "slot-heights".to_string(),
1518 ftd::p2::Kind::string().into_optional(),
1519 ),
1520 (
1521 "spacing".to_string(),
1522 ftd::p2::Kind::integer().into_optional(),
1523 ),
1524 (
1525 "inline".to_string(),
1526 ftd::p2::Kind::boolean().into_optional(),
1527 ),
1528 ],
1529 ]
1530 .concat()
1531 .into_iter()
1532 .collect();
1533
1534 ftd::Component {
1535 line_number: 0,
1536 kernel: true,
1537 root: "ftd.kernel".to_string(),
1538 full_name: "ftd#grid".to_string(),
1539 arguments,
1540 locals: Default::default(),
1541 properties: Default::default(),
1542 instructions: Default::default(),
1543 invocations: Default::default(),
1544 condition: None,
1545 events: vec![],
1546 }
1547}
1548
1549pub fn boolean_function() -> ftd::Component {
1550 ftd::Component {
1551 line_number: 0,
1552 kernel: true,
1553 root: "ftd.kernel".to_string(),
1554 full_name: "ftd#boolean".to_string(),
1555 arguments: [
1556 vec![
1557 ("value".to_string(), ftd::p2::Kind::boolean()),
1558 ("align".to_string(), ftd::p2::Kind::string().into_optional()),
1559 ("style".to_string(), ftd::p2::Kind::string().into_optional()),
1560 (
1561 "format".to_string(),
1562 ftd::p2::Kind::string().into_optional(),
1563 ),
1564 (
1565 "role".to_string(),
1566 ftd::p2::Kind::record("ftd#type").into_optional(),
1567 ),
1568 ("true".to_string(), ftd::p2::Kind::string().into_optional()),
1569 ("false".to_string(), ftd::p2::Kind::string().into_optional()),
1570 ],
1571 common_arguments(),
1572 ]
1573 .concat()
1574 .into_iter()
1575 .collect(),
1576 locals: Default::default(),
1577 properties: Default::default(),
1578 instructions: Default::default(),
1579 invocations: Default::default(),
1580 condition: None,
1581 events: vec![],
1582 }
1583}
1584
1585pub fn input_function() -> ftd::Component {
1586 ftd::Component {
1587 line_number: 0,
1588 kernel: true,
1589 root: "ftd.kernel".to_string(),
1590 full_name: "ftd#input".to_string(),
1591 arguments: [
1592 vec![
1593 (
1594 "placeholder".to_string(),
1595 ftd::p2::Kind::string().into_optional(),
1596 ),
1597 ("value".to_string(), ftd::p2::Kind::string().into_optional()),
1598 (
1599 "default-value".to_string(),
1600 ftd::p2::Kind::string().into_optional(),
1601 ),
1602 (
1603 "multiline".to_string(),
1604 ftd::p2::Kind::boolean().set_default(Some("false".to_string())),
1605 ),
1606 (
1607 "role".to_string(),
1608 ftd::p2::Kind::record("ftd#type").into_optional(),
1609 ),
1610 ("type".to_string(), ftd::p2::Kind::string().into_optional()),
1611 ],
1612 common_arguments(),
1613 ]
1614 .concat()
1615 .into_iter()
1616 .collect(),
1617 locals: Default::default(),
1618 properties: Default::default(),
1619 instructions: Default::default(),
1620 invocations: Default::default(),
1621 condition: None,
1622 events: vec![],
1623 }
1624}
1625
1626pub fn input_from_properties(
1627 unresolved_properties: &ftd::Map<ftd::component::Property>,
1628 doc: &ftd::p2::TDoc,
1629 condition: &Option<ftd::p2::Boolean>,
1630 is_child: bool,
1631 events: &[ftd::p2::Event],
1632) -> ftd::p1::Result<ftd::Input> {
1633 let reference = ftd::p2::utils::string_and_source_and_ref(
1634 0,
1635 "value",
1636 unresolved_properties,
1637 doc,
1638 condition,
1639 )
1640 .map(|v| v.2)
1641 .unwrap_or(None);
1642
1643 let properties = &ftd::component::resolve_properties(0, unresolved_properties, doc)?;
1644 let font_str = ftd::p2::utils::record_optional("role", properties, doc.name, 0)?;
1645 let mut font_reference = None;
1646 if font_str.is_some() {
1647 font_reference =
1648 ftd::p2::utils::record_and_ref(0, "role", unresolved_properties, doc, condition)?.1;
1649 }
1650 let font = font_str.map_or(Ok(None), |v| {
1651 ftd::Type::from(&v, doc, 0, font_reference).map(Some)
1652 })?;
1653
1654 Ok(ftd::Input {
1655 common: common_from_properties(
1656 unresolved_properties,
1657 doc,
1658 condition,
1659 is_child,
1660 events,
1661 reference,
1662 )?,
1663 placeholder: ftd::p2::utils::string_optional("placeholder", properties, doc.name, 0)?,
1664 multiline: ftd::p2::utils::bool_("multiline", properties, doc.name, 0)?,
1665 type_: ftd::p2::utils::string_optional("type", properties, doc.name, 0)?,
1666 value: ftd::p2::utils::string_optional("value", properties, doc.name, 0)?,
1667 default_value: ftd::p2::utils::string_optional("default-value", properties, doc.name, 0)?,
1668 font,
1669 })
1670}
1671
1672pub fn scene_from_properties(
1673 unresolved_properties: &ftd::Map<ftd::component::Property>,
1674 doc: &ftd::p2::TDoc,
1675 condition: &Option<ftd::p2::Boolean>,
1676 is_child: bool,
1677 events: &[ftd::p2::Event],
1678) -> ftd::p1::Result<ftd::Scene> {
1679 let properties = &ftd::component::resolve_properties(0, unresolved_properties, doc)?;
1680 Ok(ftd::Scene {
1681 common: common_from_properties(
1682 unresolved_properties,
1683 doc,
1684 condition,
1685 is_child,
1686 events,
1687 None,
1688 )?,
1689 container: container_from_properties(properties, doc)?,
1690 spacing: ftd::Spacing::from(ftd::p2::utils::string_optional(
1691 "spacing", properties, doc.name, 0,
1692 )?)?,
1693 })
1694}
1695
1696pub fn grid_from_properties(
1697 unresolved_properties: &ftd::Map<ftd::component::Property>,
1698 doc: &ftd::p2::TDoc,
1699 condition: &Option<ftd::p2::Boolean>,
1700 is_child: bool,
1701 events: &[ftd::p2::Event],
1702) -> ftd::p1::Result<ftd::Grid> {
1703 let properties = &ftd::component::resolve_properties(0, unresolved_properties, doc)?;
1704 Ok(ftd::Grid {
1705 slots: match ftd::p2::utils::string_optional("slots", properties, doc.name, 0)? {
1706 Some(val) => val,
1707 None => return ftd::p2::utils::e2("expected slots", doc.name, 0),
1708 },
1709 slot_widths: ftd::p2::utils::string_optional("slot-widths", properties, doc.name, 0)?,
1710 slot_heights: ftd::p2::utils::string_optional("slot-heights", properties, doc.name, 0)?,
1711 spacing: ftd::p2::utils::int_optional("spacing", properties, doc.name, 0)?,
1712 spacing_vertical: ftd::p2::utils::int_optional(
1713 "spacing-vertical",
1714 properties,
1715 doc.name,
1716 0,
1717 )?,
1718 spacing_horizontal: ftd::p2::utils::int_optional(
1719 "spacing-horizontal",
1720 properties,
1721 doc.name,
1722 0,
1723 )?,
1724 common: common_from_properties(
1725 unresolved_properties,
1726 doc,
1727 condition,
1728 is_child,
1729 events,
1730 None,
1731 )?,
1732 container: container_from_properties(properties, doc)?,
1733 inline: ftd::p2::utils::bool_with_default("inline", false, properties, doc.name, 0)?,
1734 auto_flow: ftd::p2::utils::string_optional("auto-flow", properties, doc.name, 0)?,
1735 })
1736}
1737
1738pub fn markup_from_properties(
1739 unresolved_properties: &ftd::Map<ftd::component::Property>,
1740 doc: &ftd::p2::TDoc,
1741 condition: &Option<ftd::p2::Boolean>,
1742 is_child: bool,
1743 events: &[ftd::p2::Event],
1744) -> ftd::p1::Result<ftd::Markups> {
1745 let (value, source, reference) = ftd::p2::utils::string_and_source_and_ref(
1746 0,
1747 "text",
1748 unresolved_properties,
1749 doc,
1750 condition,
1751 )?;
1752 let properties = &ftd::component::resolve_properties(0, unresolved_properties, doc)?;
1753 let font_str = ftd::p2::utils::record_optional("role", properties, doc.name, 0)?;
1754 let mut font_reference = None;
1755 if font_str.is_some() {
1756 font_reference =
1757 ftd::p2::utils::record_and_ref(0, "role", unresolved_properties, doc, condition)?.1;
1758 }
1759 let font = font_str.map_or(Ok(None), |v| {
1760 ftd::Type::from(&v, doc, 0, font_reference).map(Some)
1761 })?;
1762
1763 Ok(ftd::Markups {
1764 text: ftd::rendered::markup_line(value.as_str()),
1765 common: common_from_properties(
1766 unresolved_properties,
1767 doc,
1768 condition,
1769 is_child,
1770 events,
1771 reference,
1772 )?,
1773 children: vec![],
1774 line: source != ftd::TextSource::Body,
1775 text_align: ftd::TextAlign::from(
1776 ftd::p2::utils::string_optional("text-align", properties, doc.name, 0)?,
1777 doc.name,
1778 )?,
1779 style: ftd::Style::from(
1780 ftd::p2::utils::string_optional("style", properties, doc.name, 0)?,
1781 doc.name,
1782 )?,
1783 font,
1784 line_clamp: ftd::p2::utils::int_optional("line-clamp", properties, doc.name, 0)?,
1785 text_indent: ftd::Length::from(
1786 ftd::p2::utils::string_optional("text-indent", properties, doc.name, 0)?,
1787 doc.name,
1788 )?,
1789 })
1790}