{# Rendering components recursively. #} {# Args: #} {# component: component dictionary #} {# indent_width: indent width #} {% macro render(component, indent_width=0) %} {% filter indent(width=indent_width) %} {%- if component is not mapping %} {{- component }} {%- elif "iterable" in component %} {{- render_iterable_tag(component) }} {%- elif component.name == "match"%} {{- render_match_tag(component) }} {%- elif "cond" in component %} {{- render_condition_tag(component) }} {%- elif component.children|length %} {{- render_tag(component) }} {%- else %} {{- render_self_close_tag(component) }} {%- endif %} {% endfilter %} {% endmacro %} {# Rendering self close tag. #} {# Args: #} {# component: component dictionary #} {% macro render_self_close_tag(component) %} {%- if component.name|length %} <{{ component.name }} {{- render_props(component.props) }}{% if component.autofocus %} ref={focusRef} {% endif %}/> {%- else %} {{- component.contents }} {%- endif %} {% endmacro %} {# Rendering close tag with args and props. #} {# Args: #} {# component: component dictionary #} {% macro render_tag(component) %} <{{component.name}} {{- render_props(component.props) }}> {{ component.contents }} {% for child in component.children %} {{ render(child) }} {% endfor %} {%- endmacro %} {# Rendering condition component. #} {# Args: #} {# component: component dictionary #} {% macro render_condition_tag(component) %} { {{- component.cond_state }} ? ( {{ render(component.true_value) }} ) : ( {{ render(component.false_value) }} )} {%- endmacro %} {# Rendering iterable component. #} {# Args: #} {# component: component dictionary #} {% macro render_iterable_tag(component) %} <>{ {%- if component.iterable_type == 'dict' -%}Object.entries({{- component.iterable_state }}){%- else -%}{{- component.iterable_state }}{%- endif -%}.map(({{ component.arg_name }}, {{ component.arg_index }}) => ( {% for child in component.children %} {{ render(child) }} {% endfor %} ))} {%- endmacro %} {# Rendering props of a component. #} {# Args: #} {# component: component dictionary #} {% macro render_props(props) %} {% if props|length %} {{ props|join(" ") }}{% endif %} {% endmacro %} {# Rendering Match component. #} {# Args: #} {# component: component dictionary #} {% macro render_match_tag(component) %} { (() => { switch (JSON.stringify({{ component.cond._js_expr }})) { {% for case in component.match_cases %} {% for condition in case[:-1] %} case JSON.stringify({{ condition._js_expr }}): {% endfor %} return {{ case[-1] }}; break; {% endfor %} default: return {{ component.default }}; break; } })() } {%- endmacro %} {# Rendering content with args. #} {# Args: #} {# component: component dictionary #} {% macro render_arg_content(component) %} {% filter indent(width=2) %} {# no string below for a line break #} {({ {{component.args|join(", ")}} }) => ( {% for child in component.children %} {{ render(child) }} {% endfor %} )} {% endfilter %} {% endmacro %} {# Get react libraries import . #} {# Args: #} {# module: react module dictionary #} {% macro get_import(module)%} {%- if module.default|length and module.rest|length -%} import {{module.default}}, { {{module.rest|sort|join(", ")}} } from "{{module.lib}}" {%- elif module.default|length -%} import {{module.default}} from "{{module.lib}}" {%- elif module.rest|length -%} import { {{module.rest|sort|join(", ")}} } from "{{module.lib}}" {%- else -%} import "{{module.lib}}" {%- endif -%} {% endmacro %}