From 97429f45731eac12514ffe8a47be841b567fc4dd Mon Sep 17 00:00:00 2001 From: Marc Worrell Date: Sun, 30 Jun 2024 20:39:39 +0200 Subject: [PATCH] Fix compose block inherit (#51) --- src/template_compiler_element.erl | 4 ++- src/template_compiler_runtime_internal.erl | 33 ++++++++++++++++------ test/template_compiler_include_SUITE.erl | 6 ++++ test/test-data/compose2.tpl | 1 + 4 files changed, 34 insertions(+), 10 deletions(-) create mode 100644 test/test-data/compose2.tpl diff --git a/src/template_compiler_element.erl b/src/template_compiler_element.erl index a5790c6..7d0babc 100644 --- a/src/template_compiler_element.erl +++ b/src/template_compiler_element.erl @@ -732,7 +732,7 @@ maybe_add_include(_Token, _Method, _IsCatinclude, Ws) -> Ws. -compose({_, SrcPos, _}, Template, ArgsList, IsContextVars, Blocks, #cs{runtime=Runtime} = CState, Ws) -> +compose({_, SrcPos, _}, Template, ArgsList, IsContextVars, Blocks, #cs{runtime=Runtime, module=Module} = CState, Ws) -> {Ws1, TemplateAst} = template_compiler_expr:compile(Template, CState, Ws), ArgsListAst = erl_syntax:list([ erl_syntax:tuple([A,B]) || {A,B} <- ArgsList ]), {_BlocksWs, BlocksAsts} = template_compiler:compile_blocks(Blocks, CState), @@ -754,6 +754,7 @@ compose({_, SrcPos, _}, Template, ArgsList, IsContextVars, Blocks, #cs{runtime=R "_@is_context_vars," "_@vars," "_@block_list,", + "_@module,", "_@block_fun,", "_@context)" ], @@ -766,6 +767,7 @@ compose({_, SrcPos, _}, Template, ArgsList, IsContextVars, Blocks, #cs{runtime=R {context, erl_syntax:variable(CState#cs.context_var)}, {context_vars, erl_syntax:abstract(CState#cs.context_vars)}, {block_list, BlockListAst}, + {module, erl_syntax:atom(Module)}, {block_fun, BlockFunAst}, {is_context_vars, erl_syntax:abstract(IsContextVars)} ]), diff --git a/src/template_compiler_runtime_internal.erl b/src/template_compiler_runtime_internal.erl index 14d4673..d767e2a 100644 --- a/src/template_compiler_runtime_internal.erl +++ b/src/template_compiler_runtime_internal.erl @@ -26,7 +26,7 @@ block_call/6, block_inherit/7, include/9, - compose/10, + compose/11, call/4, print/1, unique/0 @@ -153,8 +153,17 @@ block_call(SrcPos, Block, Vars, BlockMap, Runtime, Context) -> After ] end; - {ok, [RenderFun|_]} when is_function(RenderFun) -> - RenderFun(Block, Vars, BlockMap, Context); + {ok, [{Module, RenderFun}|_]} when is_function(RenderFun) -> + case Runtime:trace_block(SrcPos, Block, Module, Context) of + ok -> + RenderFun(Block, Vars, BlockMap, Context); + {ok, Before, After} -> + [ + Before, + RenderFun(Block, Vars, BlockMap, Context), + After + ] + end; error -> % No such block, return empty data. <<>> @@ -165,8 +174,13 @@ block_call(SrcPos, Block, Vars, BlockMap, Runtime, Context) -> block_inherit(SrcPos, Module, Block, Vars, BlockMap, Runtime, Context) -> case maps:find(Block, BlockMap) of {ok, Modules} -> - case lists:dropwhile(fun(M) -> M =/= Module end, Modules) of - [Module, Next|_] -> + case lists:dropwhile( + fun + ({M, _F}) -> M =/= Module; + (M) -> M =/= Module + end, Modules) + of + [ _Module, Next | _ ] when is_atom(Next) -> case Runtime:trace_block(SrcPos, Block, Next, Context) of ok -> Next:render_block(Block, Vars, BlockMap, Context); @@ -177,7 +191,7 @@ block_inherit(SrcPos, Module, Block, Vars, BlockMap, Runtime, Context) -> After ] end; - _ -> + [] -> <<>> end; error -> @@ -258,7 +272,7 @@ include_1(SrcPos, Method, Template, Runtime, ContextVars, Vars, Context) -> end. %% @doc Compose include of a template, with overruling blocks. --spec compose(SrcPos, Template, Args, Runtime, ContextVars, IsContextVars, Vars, BlockList, BlockFun, Context) -> Output when +-spec compose(SrcPos, Template, Args, Runtime, ContextVars, IsContextVars, Vars, BlockList, BlockModule, BlockFun, Context) -> Output when SrcPos :: {File::binary(), Line::integer(), Col::integer()}, Template :: template_compiler:template(), Args :: list({atom(),term()}), @@ -267,10 +281,11 @@ include_1(SrcPos, Method, Template, Runtime, ContextVars, Vars, Context) -> IsContextVars :: boolean(), Vars :: map(), BlockList :: list( atom() ), + BlockModule :: atom(), BlockFun :: function(), % (_@BlockName@, Vars, Blocks, Context) -> _@BlockAst Context :: term(), Output :: template_compiler:render_result(). -compose(SrcPos, Template, Args, Runtime, ContextVars, IsContextVars, Vars, BlockList, BlockFun, Context) -> +compose(SrcPos, Template, Args, Runtime, ContextVars, IsContextVars, Vars, BlockList, BlockModule, BlockFun, Context) -> Vars1 = lists:foldl( fun ({'$cat', [Cat|_] = E}, Acc) when is_atom(Cat); is_binary(Cat); is_list(Cat) -> @@ -289,7 +304,7 @@ compose(SrcPos, Template, Args, Runtime, ContextVars, IsContextVars, Vars, Block true -> Runtime:set_context_vars(Args, Context); false -> Context end, - BlockMap = lists:foldl(fun(Block, Acc) -> Acc#{ Block => [ BlockFun ] } end, #{}, BlockList), + BlockMap = lists:foldl(fun(Block, Acc) -> Acc#{ Block => [ {BlockModule, BlockFun} ] } end, #{}, BlockList), {SrcFile, SrcLine, _SrcCol} = SrcPos, Options = [ {runtime, Runtime}, diff --git a/test/template_compiler_include_SUITE.erl b/test/template_compiler_include_SUITE.erl index 6e7f505..bbadeeb 100644 --- a/test/template_compiler_include_SUITE.erl +++ b/test/template_compiler_include_SUITE.erl @@ -23,6 +23,7 @@ groups() -> ,include_dynamic_test ,include_args_test ,compose_test + ,compose_inherit_test ]}]. init_per_suite(Config) -> @@ -78,6 +79,11 @@ compose_test(_Config) -> <<"AxB1yC">> = iolist_to_binary(Bin1), ok. +compose_inherit_test(_Config) -> + {ok, Bin1} = template_compiler:render("compose2.tpl", #{}, [], undefined), + <<"AxBXYC1yD">> = iolist_to_binary(Bin1), + ok. + test_data_dir(Config) -> filename:join([ filename:dirname(filename:dirname(?config(data_dir, Config))), diff --git a/test/test-data/compose2.tpl b/test/test-data/compose2.tpl new file mode 100644 index 0000000..af33cf5 --- /dev/null +++ b/test/test-data/compose2.tpl @@ -0,0 +1 @@ +A{% compose "compose_b.tpl" v=1 %}{% block a %}B{% inherit %}C{{ v }}{% endblock %}{% endcompose %}D \ No newline at end of file