Browse Source

Change "include" tag to follow Django behavior

Also support "parsed" keyword of "ssi" tag, which imitates previous
behavior of "include".
Evan Miller 14 years ago
parent
commit
fa285305ff

+ 40 - 13
src/erlydtl_compiler.erl

@@ -511,12 +511,14 @@ body_ast(DjangoParseTree, Context, TreeWalker) ->
                 {IfAstInfo, TreeWalker1} = body_ast(IfContents, Context, TreeWalkerAcc),
                 {ElseAstInfo, TreeWalker2} = body_ast(ElseContents, Context, TreeWalker1),
                 ifelse_ast({'expr', "ne", Arg1, Arg2}, IfAstInfo, ElseAstInfo, Context, TreeWalker2);                    
-            ({'include', {string_literal, _, File}}, TreeWalkerAcc) ->
-                include_ast(unescape_string_literal(File), Context, TreeWalkerAcc);
+            ({'include', {string_literal, _, File}, Args}, TreeWalkerAcc) ->
+                include_ast(unescape_string_literal(File), Args, Context, TreeWalkerAcc);
             ({'spaceless', Contents}, TreeWalkerAcc) ->
                 spaceless_ast(Contents, Context, TreeWalkerAcc);
             ({'ssi', Arg}, TreeWalkerAcc) ->
                 ssi_ast(Arg, Context, TreeWalkerAcc);
+            ({'ssi_parsed', {string_literal, _, FileName}}, TreeWalkerAcc) ->
+                ssi_parsed_ast(unescape_string_literal(FileName), Context, TreeWalkerAcc);
             ({'string', _Pos, String}, TreeWalkerAcc) -> 
                 string_ast(String, TreeWalkerAcc);
             ({'tag', {'identifier', _, Name}, Args}, TreeWalkerAcc) ->
@@ -685,7 +687,29 @@ string_ast(String, TreeWalker) ->
     % {{erl_syntax:binary([erl_syntax:binary_field(erl_syntax:integer(X)) || X <- String]), #ast_info{}}, TreeWalker}.       
 
 
-include_ast(File, Context, TreeWalker) ->
+include_ast(File, ArgList, Context, TreeWalker) ->
+    FilePath = full_path(File, Context#dtl_context.doc_root),
+    case parse(FilePath, Context) of
+        {ok, InclusionParseTree, CheckSum} ->
+            {NewScope, {ArgInfo, TreeWalker1}} = lists:mapfoldl(fun
+                    ({{identifier, _, LocalVarName}, Value}, {AstInfo1, TreeWalker1}) ->
+                        {{Ast, Info}, TreeWalker2} = value_ast(Value, false, Context, TreeWalker1),
+                        {{LocalVarName, Ast}, {merge_info(AstInfo1, Info), TreeWalker2}}
+                end, {#ast_info{}, TreeWalker}, ArgList),
+
+            {{BodyAst, BodyInfo}, TreeWalker2} = with_dependency({FilePath, CheckSum}, 
+                body_ast(InclusionParseTree, Context#dtl_context{
+                        parse_trail = [FilePath | Context#dtl_context.parse_trail],
+                        local_scopes = [NewScope]
+                    }, TreeWalker1)),
+
+            {{BodyAst, merge_info(BodyInfo, ArgInfo)}, TreeWalker2};
+        Err ->
+            throw(Err)
+    end.
+    
+% include at compile-time
+ssi_parsed_ast(File, Context, TreeWalker) ->
     FilePath = full_path(File, Context#dtl_context.doc_root),
     case parse(FilePath, Context) of
         {ok, InclusionParseTree, CheckSum} ->
@@ -694,7 +718,15 @@ include_ast(File, Context, TreeWalker) ->
         Err ->
             throw(Err)
     end.
-    
+
+% include at run-time
+ssi_ast(FileName, Context, TreeWalker) ->
+    {{Ast, Info}, TreeWalker1} = value_ast(FileName, true, Context, TreeWalker),
+    {Mod, Fun} = Context#dtl_context.reader,
+    {{erl_syntax:application(
+                erl_syntax:atom(erlydtl_runtime),
+                erl_syntax:atom(read_file),
+                [erl_syntax:atom(Mod), erl_syntax:atom(Fun), erl_syntax:string(Context#dtl_context.doc_root), Ast]), Info}, TreeWalker1}.
 
 filter_tag_ast(FilterList, Contents, Context, TreeWalker) ->
     {{InnerAst, Info}, TreeWalker1} = body_ast(Contents, Context#dtl_context{auto_escape = did}, TreeWalker),
@@ -970,14 +1002,6 @@ now_ast(FormatString, _Context, TreeWalker) ->
         [erl_syntax:string(UnescapeOuter)]),
         #ast_info{}}, TreeWalker}.
 
-ssi_ast(FileName, Context, TreeWalker) ->
-    {{Ast, Info}, TreeWalker1} = value_ast(FileName, true, Context, TreeWalker),
-    {Mod, Fun} = Context#dtl_context.reader,
-    {{erl_syntax:application(
-                erl_syntax:atom(erlydtl_runtime),
-                erl_syntax:atom(read_file),
-                [erl_syntax:atom(Mod), erl_syntax:atom(Fun), Ast]), Info}, TreeWalker1}.
-
 spaceless_ast(Contents, Context, TreeWalker) ->
     {{Ast, Info}, TreeWalker1} = body_ast(Contents, Context, TreeWalker),
     {{erl_syntax:application(
@@ -1005,7 +1029,10 @@ unescape_string_literal([C | Rest], Acc, slash) ->
 
 
 full_path(File, DocRoot) ->
-    filename:join([DocRoot, File]).
+    case filename:absname(File) of
+        File -> File;
+        _ -> filename:join([DocRoot, File])
+    end.
         
 %%-------------------------------------------------------------------
 %% Custom tags

+ 6 - 1
src/erlydtl_parser.yrl

@@ -154,6 +154,7 @@ Terminals
     or_keyword
     open_tag
     open_var
+    parsed_keyword
     spaceless_keyword
     ssi_keyword
     string_literal
@@ -232,7 +233,10 @@ BlockBraced -> open_tag block_keyword identifier close_tag : '$3'.
 EndBlockBraced -> open_tag endblock_keyword close_tag.
 
 ExtendsTag -> open_tag extends_keyword string_literal close_tag : {extends, '$3'}.
-IncludeTag -> open_tag include_keyword string_literal close_tag : {include, '$3'}.
+
+IncludeTag -> open_tag include_keyword string_literal close_tag : {include, '$3', []}.
+IncludeTag -> open_tag include_keyword string_literal with_keyword Args close_tag : {include, '$3', '$5'}.
+
 NowTag -> open_tag now_keyword string_literal close_tag : {date, now, '$3'}.
 
 CommentBlock -> CommentBraced Elements EndCommentBraced : {comment, '$2'}.
@@ -304,6 +308,7 @@ EndIfNotEqualBraced -> open_tag endifnotequal_keyword close_tag.
 SpacelessBlock -> open_tag spaceless_keyword close_tag Elements open_tag endspaceless_keyword close_tag : {spaceless, '$4'}.
 
 SSITag -> open_tag ssi_keyword Value close_tag : {ssi, '$3'}.
+SSITag -> open_tag ssi_keyword string_literal parsed_keyword close_tag : {ssi_parsed, '$3'}.
 
 TemplatetagTag -> open_tag templatetag_keyword Templatetag close_tag : {templatetag, '$3'}.
 

+ 6 - 3
src/erlydtl_runtime.erl

@@ -200,7 +200,10 @@ spaceless(Contents) ->
     Contents4 = re:replace(Contents3, ">\s+<", "><", [global, {return,list}]),
     Contents4.
 
-read_file(Module, Function, FileName) ->
-    FileName = filename:absname(FileName),
-    {ok, Binary} = Module:Function(FileName),
+read_file(Module, Function, DocRoot, FileName) ->
+    AbsName = case filename:absname(FileName) of
+        FileName -> FileName;
+        _ -> filename:join([DocRoot, FileName])
+    end,
+    {ok, Binary} = Module:Function(AbsName),
     binary_to_list(Binary).

+ 1 - 1
src/erlydtl_scanner.erl

@@ -92,7 +92,7 @@ scan([], Scanned, _, in_text) ->
                             
                             "spaceless", "endspaceless", 
                             
-                            "ssi", 
+                            "ssi", "parsed",
                             
                             "templatetag", "openblock", "closeblock", "openvariable", "closevariable", "openbrace", "closebrace", "opencomment", "closecomment",
 

+ 1 - 1
tests/input/include

@@ -1 +1 @@
-Including another file: {% include "include.html" %}
+Including another file: {% include "include.html" with var1=var1 %}

+ 2 - 2
tests/input/include_path

@@ -1,5 +1,5 @@
 main file
 
-{% include "path1/template1" %}
+{% ssi "path1/template1" parsed %}
 
-{{ base_var }}
+{{ base_var }}