Browse files

Fix various custom tag issues

  • Loading branch information...
1 parent 6b746f2 commit 8b1e64bd9343bc3c99370093566681620421f312 @evanmiller evanmiller committed Jan 17, 2013
View
8 README.markdown
@@ -62,10 +62,8 @@ with one of the following signatures:
The `TagVars` are variables provided to a custom tag in the template's body
(e.g. `{% foo bar=100 %}` results in `TagVars = [{"bar", 100}]`).
The `Options` are options passed as the second argument to the `render/2` call
-at render-time. For backward compatibility, if render `Options` include
-a `custom_tags_context` option, its value will be passed as `Options` to the
-custom tag handling function. Note that this backward-compatibility functionality
-will be deprecated in one of the next releases.
+at render-time. (These may include any options, not just `locale` and
+`translation_fun`.)
* `custom_filters_modules` - A list of modules to be used for handling custom
filters. The modules will be searched in order and take precedence over the
@@ -153,8 +151,6 @@ Val end`
* `locale` - A string specifying the current locale, for use with the
`blocktrans_fun` compile-time option.
-* `custom_tags_context` - A value that will be passed to custom tags.
-
my_compiled_template:translatable_strings() -> [String]
List of strings appearing in `{% trans %}` tags that can be overridden with
View
80 src/erlydtl_compiler.erl
@@ -184,17 +184,18 @@ write_binary(Module1, Bin, Options, Warnings) ->
end.
compile_multiple_to_binary(Dir, ParserResults, Context) ->
+ MatchAst = options_match_ast(),
{Functions, {AstInfo, _}} = lists:mapfoldl(fun({File, DjangoParseTree, CheckSum}, {AstInfo, TreeWalker}) ->
FilePath = full_path(File, Context#dtl_context.doc_root),
{{BodyAst, BodyInfo}, TreeWalker1} = with_dependency({FilePath, CheckSum}, body_ast(DjangoParseTree, Context, TreeWalker)),
FunctionName = filename:rootname(filename:basename(File)),
Function1 = erl_syntax:function(erl_syntax:atom(FunctionName),
[erl_syntax:clause([erl_syntax:variable("_Variables")], none,
[erl_syntax:application(none, erl_syntax:atom(FunctionName),
- [erl_syntax:variable("_Variables"), erl_syntax:atom(none)])])]),
+ [erl_syntax:variable("_Variables"), erl_syntax:list([])])])]),
Function2 = erl_syntax:function(erl_syntax:atom(FunctionName),
- [erl_syntax:clause([erl_syntax:variable("_Variables"), erl_syntax:variable("_TranslationFun")], none,
- [BodyAst])]),
+ [erl_syntax:clause([erl_syntax:variable("_Variables"), erl_syntax:variable("RenderOptions")], none,
+ MatchAst ++ [BodyAst])]),
{{FunctionName, Function1, Function2}, {merge_info(AstInfo, BodyInfo), TreeWalker1}}
end, {#ast_info{}, #treewalker{}}, ParserResults),
Forms = custom_forms(Dir, Context#dtl_context.module, Functions, AstInfo),
@@ -345,8 +346,9 @@ custom_tags_clauses_ast(CustomTags, Context, TreeWalker) ->
custom_tags_clauses_ast1(CustomTags, [], [], #ast_info{}, Context, TreeWalker).
custom_tags_clauses_ast1([], _ExcludeTags, ClauseAcc, InfoAcc, _Context, TreeWalker) ->
- {{lists:reverse([erl_syntax:clause([erl_syntax:underscore(), erl_syntax:underscore(), erl_syntax:underscore()], none,
- [erl_syntax:list([])])|ClauseAcc]), InfoAcc}, TreeWalker};
+ {{lists:reverse([erl_syntax:clause([erl_syntax:variable("TagName"), erl_syntax:underscore(), erl_syntax:underscore()], none,
+ [erl_syntax:list([])])|ClauseAcc
+ ]), InfoAcc}, TreeWalker};
custom_tags_clauses_ast1([Tag|CustomTags], ExcludeTags, ClauseAcc, InfoAcc, Context, TreeWalker) ->
case lists:member(Tag, ExcludeTags) of
true ->
@@ -357,13 +359,12 @@ custom_tags_clauses_ast1([Tag|CustomTags], ExcludeTags, ClauseAcc, InfoAcc, Cont
true ->
case parse(CustomTagFile, Context) of
{ok, DjangoParseTree, CheckSum} ->
- {{BodyAst, BodyAstInfo}, TreeWalker1} =
- with_dependency({CustomTagFile, CheckSum},
- body_ast(DjangoParseTree, Context, TreeWalker)),
+ {{BodyAst, BodyAstInfo}, TreeWalker1} = with_dependency(
+ {CustomTagFile, CheckSum}, body_ast(DjangoParseTree, Context, TreeWalker)),
+ MatchAst = options_match_ast(),
Clause = erl_syntax:clause(
- [erl_syntax:string(Tag),
- erl_syntax:variable("_Variables"), options_ast()],
- none, [BodyAst]),
+ [key_to_string(Tag), erl_syntax:variable("_Variables"), erl_syntax:variable("RenderOptions")],
+ none, MatchAst ++ [BodyAst]),
custom_tags_clauses_ast1(CustomTags, [Tag|ExcludeTags],
[Clause|ClauseAcc], merge_info(BodyAstInfo, InfoAcc),
Context, TreeWalker1);
@@ -438,24 +439,14 @@ forms(File, Module, {BodyAst, BodyInfo}, {CustomTagsFunctionAst, CustomTagsInfo}
erl_syntax:atom(render),
[erl_syntax:variable("_Variables"), erl_syntax:list([])])])]),
Function2 = erl_syntax:application(none, erl_syntax:atom(render_internal),
- [erl_syntax:variable("_Variables"),
- erl_syntax:application(
- erl_syntax:atom(proplists),
- erl_syntax:atom(get_value),
- [erl_syntax:atom(translation_fun), erl_syntax:variable("Options"), erl_syntax:atom(none)]),
- erl_syntax:application(
- erl_syntax:atom(proplists),
- erl_syntax:atom(get_value),
- [erl_syntax:atom(locale), erl_syntax:variable("Options"), erl_syntax:atom(none)]),
- erl_syntax:variable("Options")
- ]),
+ [erl_syntax:variable("_Variables"), erl_syntax:variable("RenderOptions")]),
ClauseOk = erl_syntax:clause([erl_syntax:variable("Val")], none,
[erl_syntax:tuple([erl_syntax:atom(ok), erl_syntax:variable("Val")])]),
ClauseCatch = erl_syntax:clause([erl_syntax:variable("Err")], none,
[erl_syntax:tuple([erl_syntax:atom(error), erl_syntax:variable("Err")])]),
Render2FunctionAst = erl_syntax:function(erl_syntax:atom(render),
[erl_syntax:clause([erl_syntax:variable("_Variables"),
- erl_syntax:variable("Options")], none,
+ erl_syntax:variable("RenderOptions")], none,
[erl_syntax:try_expr([Function2], [ClauseOk], [ClauseCatch])])]),
SourceFunctionTuple = erl_syntax:tuple(
@@ -472,15 +463,9 @@ forms(File, Module, {BodyAst, BodyInfo}, {CustomTagsFunctionAst, CustomTagsInfo}
VariablesAst = variables_function(MergedInfo#ast_info.var_names),
- BodyAstTmp = [
- erl_syntax:match_expr(
- erl_syntax:variable("_CustomTagOptions"),
- erl_syntax:application(
- erl_syntax:atom(proplists),
- erl_syntax:atom(get_value),
- [erl_syntax:atom(custom_tags_context),
- erl_syntax:variable("RenderOptions"),
- erl_syntax:variable("RenderOptions")])),
+ MatchAst = options_match_ast(),
+
+ BodyAstTmp = MatchAst ++ [
erl_syntax:application(
erl_syntax:atom(erlydtl_runtime),
erl_syntax:atom(stringify_final),
@@ -491,8 +476,6 @@ forms(File, Module, {BodyAst, BodyInfo}, {CustomTagsFunctionAst, CustomTagsInfo}
erl_syntax:atom(render_internal),
[erl_syntax:clause([
erl_syntax:variable("_Variables"),
- erl_syntax:variable("_TranslationFun"),
- erl_syntax:variable("_CurrentLocale"),
erl_syntax:variable("RenderOptions")],
none, BodyAstTmp)]
),
@@ -515,6 +498,21 @@ forms(File, Module, {BodyAst, BodyInfo}, {CustomTagsFunctionAst, CustomTagsInfo}
TranslatedBlocksAst, VariablesAst, RenderInternalFunctionAst,
CustomTagsFunctionAst | BodyInfo#ast_info.pre_render_asts]].
+options_match_ast() ->
+ [
+ erl_syntax:match_expr(
+ erl_syntax:variable("_TranslationFun"),
+ erl_syntax:application(
+ erl_syntax:atom(proplists),
+ erl_syntax:atom(get_value),
+ [erl_syntax:atom(translation_fun), erl_syntax:variable("RenderOptions"), erl_syntax:atom(none)])),
+ erl_syntax:match_expr(
+ erl_syntax:variable("_CurrentLocale"),
+ erl_syntax:application(
+ erl_syntax:atom(proplists),
+ erl_syntax:atom(get_value),
+ [erl_syntax:atom(locale), erl_syntax:variable("RenderOptions"), erl_syntax:atom(none)]))
+ ].
% child templates should only consist of blocks at the top level
body_ast([{'extends', {string_literal, _Pos, String}} | ThisParseTree], Context, TreeWalker) ->
@@ -1270,18 +1268,18 @@ tag_ast(Name, Args, Context, TreeWalker) ->
custom_tags_modules_ast(Name, InterpretedArgs, #dtl_context{ custom_tags_modules = [], is_compiling_dir = false }) ->
{erl_syntax:application(none, erl_syntax:atom(render_tag),
[key_to_string(Name), erl_syntax:list(InterpretedArgs),
- erl_syntax:variable("_CustomTagOptions")]),
+ erl_syntax:variable("RenderOptions")]),
#ast_info{custom_tags = [Name]}};
custom_tags_modules_ast(Name, InterpretedArgs, #dtl_context{ custom_tags_modules = [], is_compiling_dir = true, module = Module }) ->
{erl_syntax:application(erl_syntax:atom(Module), erl_syntax:atom(Name),
- [erl_syntax:list(InterpretedArgs), erl_syntax:variable("_CustomTagOptions")]),
+ [erl_syntax:list(InterpretedArgs), erl_syntax:variable("RenderOptions")]),
#ast_info{ custom_tags = [Name] }};
custom_tags_modules_ast(Name, InterpretedArgs, #dtl_context{ custom_tags_modules = [Module|Rest] } = Context) ->
try lists:max([I || {N,I} <- Module:module_info(exports), N =:= Name]) of
2 ->
{erl_syntax:application(erl_syntax:atom(Module), erl_syntax:atom(Name),
[erl_syntax:list(InterpretedArgs),
- erl_syntax:variable("_CustomTagOptions")]), #ast_info{}};
+ erl_syntax:variable("RenderOptions")]), #ast_info{}};
1 ->
{erl_syntax:application(erl_syntax:atom(Module), erl_syntax:atom(Name),
[erl_syntax:list(InterpretedArgs)]), #ast_info{}};
@@ -1297,12 +1295,6 @@ print(true, Fmt, Args) ->
print(_, _Fmt, _Args) ->
ok.
-options_ast() ->
- erl_syntax:list([
- erl_syntax:tuple([erl_syntax:atom(translation_fun), erl_syntax:variable("_TranslationFun")]),
- erl_syntax:tuple([erl_syntax:atom(locale), erl_syntax:variable("_CurrentLocale")])
- ]).
-
call_ast(Module, TreeWalkerAcc) ->
call_ast(Module, erl_syntax:variable("_Variables"), #ast_info{}, TreeWalkerAcc).
@@ -1314,7 +1306,7 @@ call_ast(Module, Variable, AstInfo, TreeWalker) ->
AppAst = erl_syntax:application(
erl_syntax:atom(Module),
erl_syntax:atom(render),
- [Variable, options_ast()]),
+ [Variable, erl_syntax:variable("RenderOptions")]),
RenderedAst = erl_syntax:variable("Rendered"),
OkAst = erl_syntax:clause(
[erl_syntax:tuple([erl_syntax:atom(ok), RenderedAst])],
View
2 tests/input/custom_call
@@ -4,4 +4,4 @@
>>>> before custom call tag 'if'
{% call example_if with var1 %}
->>>> after custom call tag 'if'
+>>>> after custom call tag 'if'
View
2 tests/src/erlydtl_custom_tags.erl
@@ -5,7 +5,7 @@
custom1(_TagVars = []) ->
<<"b1">>.
-custom2([], _CustomTagsContext = ctx) ->
+custom2([], _RenderOptions = [{locale, ru}, {foo, bar}]) ->
<<"b2">>.
custom3([], _RenderOptions = [{locale, ru}]) ->
View
4 tests/src/erlydtl_functional_tests.erl
@@ -159,9 +159,9 @@ setup("trans") ->
setup("locale") ->
{ok, _RenderVars = [{locale, "ru"}]};
setup("custom_tag1") ->
- {ok, [{a, <<"a1">>}], [{locale, ru}, {custom_tags_context, ctx}], [<<"b1">>, <<"\n">>]};
+ {ok, [{a, <<"a1">>}], [{locale, ru}], [<<"b1">>, <<"\n">>]};
setup("custom_tag2") ->
- {ok, [{a, <<"a1">>}], [{locale, ru}, {custom_tags_context, ctx}], [<<"b2">>, <<"\n">>]};
+ {ok, [{a, <<"a1">>}], [{locale, ru}, {foo, bar}], [<<"b2">>, <<"\n">>]};
setup("custom_tag3") ->
{ok, [{a, <<"a1">>}], [{locale, ru}], [<<"b3">>, <<"\n">>]};
setup("ssi") ->

0 comments on commit 8b1e64b

Please sign in to comment.