Example #1
0
    def simplify(self, changes):
        retval = super(HtmlList, self).simplify(changes)
        if retval is not self:
            return retval

        def is_html_text_call(item):
            return (
                isinstance(item, codegen.FunctionCall)
                and isinstance(item.expr, codegen.VariableReference)
                and (
                    "{0}.{1}".format(item.expr.module_name, item.expr.name)
                    == "Html.text"
                )
            )

        new_items = []
        for item in self.items:
            if (
                len(new_items) > 0
                and is_html_text_call(new_items[-1])
                and is_html_text_call(item)
            ):
                last_item = new_items[-1]
                if not isinstance(last_item.args[0], codegen.StringConcat):
                    last_item.args = [codegen.StringConcat([last_item.args[0]])]

                last_item.args[0].parts.append(item.args[0])
                changes.append(True)
            else:
                new_items.append(item)
        self.items = new_items
        return self
Example #2
0
 def test_string_join_omit_empty_2(self):
     scope = codegen.Scope()
     scope.reserve_name("tmp", type=dtypes.String)
     var = scope.variables["tmp"]
     join = codegen.StringConcat([codegen.String(""), var])
     join = codegen.simplify(join)
     self.assertCodeEqual(
         join.as_source_code(),
         """
         tmp
     """,
     )
Example #3
0
 def test_string_join_two(self):
     scope = codegen.Scope()
     scope.reserve_name("tmp", type=dtypes.String)
     var = scope.variables["tmp"]
     join = codegen.StringConcat([codegen.String("hello "), var])
     self.assertCodeEqual(
         join.as_source_code(),
         """
         String.concat [ "hello "
                       , tmp
                       ]
     """,
     )
Example #4
0
 def test_string_join_collapse_strings(self):
     scope = codegen.Scope()
     scope.reserve_name("tmp", type=dtypes.String)
     var = scope.variables["tmp"]
     join1 = codegen.StringConcat([
         codegen.String("hello "),
         codegen.String("there "),
         var,
         codegen.String(" how"),
         codegen.String(" are you?"),
     ])
     join1 = codegen.simplify(join1)
     self.assertCodeEqual(
         join1.as_source_code(),
         """
         String.concat [ "hello there "
                       , tmp
                       , " how are you?"
                       ]
         """,
     )
Example #5
0
def dom_nodes_to_elm(nodes, expr_replacements, local_scope, compiler_env):
    # We have to structure this as a list of lists, then do a List.concat
    # at the end. In many cases the List.concat will disappear after
    # simplify.
    from elm_fluent import compiler

    items = []
    for node in nodes:
        if isinstance(node, bs4.element.NavigableString):
            parts = interpolate_replacements(text_type(node), expr_replacements)
            for part in parts:
                if isinstance(part, string_types):
                    items.append(
                        HtmlList(
                            [
                                local_scope.variables["Html.text"].apply(
                                    codegen.String(text_type(part))
                                )
                            ]
                        )
                    )
                else:
                    val = compiler.compile_expr(part, local_scope, compiler_env)
                    if val.type == html_output_type:
                        # This is a list type, so simply append to our list of lists
                        items.append(val)
                    else:
                        val = local_scope.variables["Html.text"].apply(
                            compiler.Stringable(val, local_scope)
                        )
                        items.append(HtmlList([val]))
        else:
            assert isinstance(node, bs4.element.Tag)
            tag_name = node.name.lower()
            static_attributes = []
            for attr_name, attr_value in sorted(node.attrs.items()):
                if isinstance(attr_value, list):
                    # Bs4 treats class attribute differently, returns a list, which we convert
                    # back to a string here:
                    attr_value = " ".join(attr_value)

                attr_value_parts = interpolate_replacements(
                    attr_value, expr_replacements
                )
                attr_output_parts = []
                for part in attr_value_parts:
                    if isinstance(part, string_types):
                        attr_output_parts.append(codegen.String(text_type(part)))
                    else:
                        with compiler_env.modified(html_context=False):
                            attr_output_parts.append(
                                compiler.Stringable(
                                    compiler.compile_expr(
                                        part, local_scope, compiler_env
                                    ),
                                    local_scope,
                                    from_ftl_source=compiler.make_ftl_source(
                                        part, compiler_env
                                    ),
                                )
                            )

                attr_final_value = codegen.StringConcat(attr_output_parts)

                if attr_name in html_attributes.ATTRIBUTES:
                    attr_constructor = local_scope.variables[
                        "Attributes.{0}".format(attr_name)
                    ]
                else:
                    attr_constructor = local_scope.variables[
                        "Attributes.attribute"
                    ].apply(codegen.String(attr_name))
                static_attributes.append(attr_constructor.apply(attr_final_value))

            if compiler_env.dynamic_html_attributes:
                selectors_for_node = codegen.List(
                    list(
                        map(
                            codegen.String,
                            get_selectors_for_node(node, expr_replacements),
                        )
                    )
                )
                dynamic_attributes = local_scope.variables[
                    "Fluent.selectAttributes"
                ].apply(
                    local_scope.variables[compiler.ATTRS_ARG_NAME], selectors_for_node
                )
            else:
                dynamic_attributes = codegen.List([])
            attributes = codegen.ListConcat(
                [codegen.List(static_attributes), dynamic_attributes],
                dtypes.List.specialize(a=html.Attribute),
            )

            sub_items = dom_nodes_to_elm(
                list(node.children), expr_replacements, local_scope, compiler_env
            )
            if tag_name in html.ELEMENTS:
                node_constructor = local_scope.variables["Html.{0}".format(tag_name)]
            else:
                node_constructor = local_scope.variables["Html.node"].apply(
                    codegen.String(tag_name)
                )
            item = node_constructor.apply(attributes, sub_items)
            items.append(HtmlList([item]))

    return HtmlListConcat(items)
Example #6
0
 def test_string_join_one(self):
     join = codegen.StringConcat([codegen.String("hello")])
     join = codegen.simplify(join)
     self.assertCodeEqual(join.as_source_code(), '"hello"')
Example #7
0
 def test_string_join_empty(self):
     join = codegen.StringConcat([])
     join = codegen.simplify(join)
     self.assertCodeEqual(join.as_source_code(), '""')