Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
rsaccon committed Nov 18, 2007
0 parents commit f84b2a8
Show file tree
Hide file tree
Showing 25 changed files with 957 additions and 0 deletions.
2 changes: 2 additions & 0 deletions Emakefile
@@ -0,0 +1,2 @@
{"src/erlydtl/*", [debug_info, {d, debug}, {outdir, "ebin"}]}.
{"src/demo/*", [debug_info, {d, debug}, {outdir, "ebin"}]}.
15 changes: 15 additions & 0 deletions Makefile
@@ -0,0 +1,15 @@
ERL=/Users/rsaccon/R11B/start.sh
#ERL=/usr/local/erlware/bin/erl
ERL=erl
NODENAME=skast


all:
$(ERL) -make

run:
$(ERL) -pa `pwd`/ebin

clean:
rm -fv ebin/*
rm -fv erl_crash.dump
12 changes: 12 additions & 0 deletions demo/out/test_comment.html
@@ -0,0 +1,12 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Test Comment</title>
</head>
<body>

bla

</body>
</html>
11 changes: 11 additions & 0 deletions demo/out/test_extend.html
@@ -0,0 +1,11 @@
blastring

base template

replacing the base title

more of base template

replacing the base content

end of base template
11 changes: 11 additions & 0 deletions demo/out/test_variable.html
@@ -0,0 +1,11 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Test variable</title>
</head>
<body>
foostring
foostring
</body>
</html>
11 changes: 11 additions & 0 deletions demo/templates/base.html
@@ -0,0 +1,11 @@
{{ variable }}

base template

{% block title %}base title{% endblock %}

more of base template

{% block content %}base content{% endblock %}

end of base template
12 changes: 12 additions & 0 deletions demo/templates/test_comment.html
@@ -0,0 +1,12 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Test Comment</title>
</head>
<body>
{# comment1 #}
bla
{# comment2 #}
</body>
</html>
3 changes: 3 additions & 0 deletions demo/templates/test_extend.html
@@ -0,0 +1,3 @@
{% extends base.html %}
{% block title %}replacing the base title{% endblock %}
{% block content %}replacing the base content{% endblock %}
11 changes: 11 additions & 0 deletions demo/templates/test_variable.html
@@ -0,0 +1,11 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Test variable</title>
</head>
<body>
{{ variable }}
<!--{{ variable }}-->
</body>
</html>
Binary file added ebin/base.beam
Binary file not shown.
Binary file added ebin/erlydtl.beam
Binary file not shown.
Binary file added ebin/erlydtl_api.beam
Binary file not shown.
Binary file added ebin/erlydtl_demo.beam
Binary file not shown.
Binary file added ebin/erlydtl_parser.beam
Binary file not shown.
Binary file added ebin/erlydtl_scanner.beam
Binary file not shown.
Binary file added ebin/erlydtl_tools.beam
Binary file not shown.
Binary file added ebin/test_comment.beam
Binary file not shown.
Binary file added ebin/test_extend.beam
Binary file not shown.
Binary file added ebin/test_variable.beam
Binary file not shown.
104 changes: 104 additions & 0 deletions src/demo/erlydtl_demo.erl
@@ -0,0 +1,104 @@
%%%-------------------------------------------------------------------
%%% File: erlydtl_demo.erl
%%% @author Roberto Saccon <rsaccon@gmail.com> [http://rsaccon.com]
%%% @copyright 2007 Roberto Saccon
%%% @doc
%%%
%%% @end
%%%
%%% The MIT License
%%%
%%% Copyright (c) 2007 Roberto Saccon
%%%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy
%%% of this software and associated documentation files (the "Software"), to deal
%%% in the Software without restriction, including without limitation the rights
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
%%% copies of the Software, and to permit persons to whom the Software is
%%% furnished to do so, subject to the following conditions:
%%%
%%% The above copyright notice and this permission notice shall be included in
%%% all copies or substantial portions of the Software.
%%%
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
%%% THE SOFTWARE.
%%%
%%% @since 2007-11-17 by Roberto Saccon
%%%-------------------------------------------------------------------
-module(erlydtl_demo).
-author('rsaccon@gmail.com').

%% API
-export([compile_templates/0,
render_html/0]).

%%====================================================================
%% API
%%====================================================================
%%--------------------------------------------------------------------
%% @spec () -> any()
%% @doc compiles the templates to beam files
%% @end
%%--------------------------------------------------------------------
compile_templates() ->
DocRoot = filename:join([filename:dirname(code:which(?MODULE)),"..", "demo", "templates"]),
filelib:fold_files(DocRoot,
"\.",
true,
fun(Path, _Acc) ->
Name = filename:rootname(filename:basename(Path)),
erlydtl_api:compile(Path, Name, Name, DocRoot)
end,
[]).


%%--------------------------------------------------------------------
%% @spec () -> any()
%% @doc renders the templete to a file
%% @end
%%--------------------------------------------------------------------
render_html() ->
OutDir = filename:join([filename:dirname(code:which(?MODULE)),"..", "demo", "out"]),
render(OutDir, test_variable, ".html", "foostring"),
render(OutDir, test_extend, ".html", "blastring"),
render(OutDir, test_comment, ".html").


%%====================================================================
%% Internal functions
%%====================================================================

render(OutDir, Name, Ext, Var) ->
case catch Name:Name(Var) of
{'EXIT', Reason} ->
io:format("TRACE ~p:~p ~p: rendering failure: ~n",[?MODULE, ?LINE, Reason]);
Val ->
case file:open(filename:join([OutDir, lists:concat([Name, Ext])]), [write]) of
{ok, IoDev} ->
file:write(IoDev, Val),
file:close(IoDev),
io:format("TRACE ~p:~p ~p: success~n",[?MODULE, ?LINE, Name]);
_ ->
io:format("TRACE ~p:~p ~p: file write failure~n",[?MODULE, ?LINE, Name])
end
end.

render(OutDir, Name, Ext) ->
case catch Name:Name() of
{'EXIT', Reason} ->
io:format("TRACE ~p:~p ~p: rendering failure: ~n",[?MODULE, ?LINE, Reason]);
Val ->
case file:open(filename:join([OutDir, lists:concat([Name, Ext])]), [write]) of
{ok, IoDev} ->
file:write(IoDev, Val),
file:close(IoDev),
io:format("TRACE ~p:~p ~p: success~n",[?MODULE, ?LINE, Name]);
_ ->
io:format("TRACE ~p:~p ~p: file write failure~n",[?MODULE, ?LINE, Name])
end
end.
175 changes: 175 additions & 0 deletions src/erlydtl/erlydtl_api.erl
@@ -0,0 +1,175 @@
%%%-------------------------------------------------------------------
%%% File: erlydtl_api.erl
%%% @author Roberto Saccon <rsaccon@gmail.com> [http://rsaccon.com]
%%% @copyright 2007 Roberto Saccon
%%% @doc
%%% API for compiling ErlyDTL templeates
%%% @end
%%%
%%% The MIT License
%%%
%%% Copyright (c) 2007 Roberto Saccon
%%%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy
%%% of this software and associated documentation files (the "Software"), to deal
%%% in the Software without restriction, including without limitation the rights
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
%%% copies of the Software, and to permit persons to whom the Software is
%%% furnished to do so, subject to the following conditions:
%%%
%%% The above copyright notice and this permission notice shall be included in
%%% all copies or substantial portions of the Software.
%%%
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
%%% THE SOFTWARE.
%%%
%%% @since 2007-11-17 by Roberto Saccon
%%%-------------------------------------------------------------------
-module(erlydtl_api).
-author('rsaccon@gmail.com').

%% API
-export([compile/4]).


%%--------------------------------------------------------------------
%% @spec (File:string(), ModuleName:string(), FunctionName:atom(), DocRoot:string()) ->
%% {Ok::atom, Ast::tuple() | {Error::atom(), Msg:string()}
%% @doc compiles a template to a beam file
%% @end
%%--------------------------------------------------------------------
compile(File, ModuleName, FunctionName, DocRoot) ->
case parse(File) of
{ok, Ast} ->
RelDir = rel_dir(filename:dirname(File), DocRoot),
compile_reload(Ast, ModuleName, FunctionName, RelDir);
{error, Msg} = Err ->
io:format("TRACE ~p:~p ~p~n",[?MODULE, ?LINE, File ++ " Parser failure:"]),
io:format("TRACE ~p:~p ~p~n",[?MODULE, ?LINE, Msg]),
Err
end.


%%====================================================================
%% Internal functions
%%====================================================================

rel_dir(Dir, DocRoot) when Dir =:= DocRoot ->
DocRoot;
rel_dir(Dir, DocRoot) ->
RelFile = string:substr(Dir, length(DocRoot)+2),
filename:join([DocRoot, RelFile]).


parse(File) ->
case file:read_file(File) of
{ok, B} ->
case erlydtl_scanner:scan(binary_to_list(B)) of
{ok, Tokens} ->
erlydtl_parser:parse(Tokens);
Err ->
io:format("TRACE ~p:~p ~p~n",[?MODULE, ?LINE, File ++ " Scanner failure:"]),
io:format("TRACE ~p:~p ~p~n",[?MODULE, ?LINE, Err]),
Err
end;
Err ->
io:format("TRACE ~p:~p ~p~n",[?MODULE, ?LINE, "File read error"]),
Err
end.


compile_reload([H | T], ModuleName, FunctionName, RelDir) ->
{List, Args} = case transl(H, T, [], [], RelDir) of
{regular, List0, Args0} ->
{[inplace_block(X) || X <- List0], Args0};
{inherited, List0, Arg0} ->
{List0, Arg0}
end,
Args2 = lists:reverse([{var, 1, Val} || {Val, _} <- Args]),
Cons = list_fold(lists:reverse(List)),
Ast2 = {function, 1, list_to_atom(FunctionName), length(Args2),
[{clause, 1, Args2, [], [Cons]}]},
Ac = erlydtl_tools:create_module(Ast2 , ModuleName),
case compile:forms(Ac) of
{ok, Module, Bin} ->
case erlydtl_tools:reload(Module, Bin) of
ok ->
erlydtl_tools:write_beam(Module, Bin, "ebin");
_ ->
{error, "reload failed"}
end;
_ ->
{error, "compilation failed"}
end.


list_fold([E]) ->
E;
list_fold([E1, E2]) ->
{cons, 1, E2, E1};
list_fold([E1, E2 | Tail]) ->
lists:foldl(fun(X, T) ->
{cons, 1, X, T}
end, {cons, 1, E2, E1}, Tail).


transl(nil, [{extends, _, Name}], Out, Args, RelDir) ->
case parse(filename:join([RelDir, Name])) of
{ok, ParentAst} ->
[H|T]=ParentAst,
{_, List, Args1} = transl(H, T, [], [], RelDir),
{inherited, [replace_block(X, Out) || X <- List], Args1};
{error, Msg} ->
io:format("TRACE ~p:~p ~p~n",[?MODULE, ?LINE, Msg]),
io:format("TRACE ~p:~p Parent Parser failure: ~p~n",[?MODULE, ?LINE, Name]),
{regular, Out, Args}
end;

transl(nil, [{var, L, Val}], Out, Args, _) ->
case lists:keysearch(Val, 2, Args) of
false ->
Key = list_to_atom(lists:concat(["A", length(Args) + 1])),
{regular, [{var, L, Key} | Out], [{Key, Val} | Args]};
{value, {Key, _}} ->
{regular, [{var, L, Key} | Out], Args}
end;

transl(nil, [Token], Out, Args, _) ->
{regular, [Token | Out], Args};

transl([H | T], [{var, L, Val}], Out, Args, DocRoot) ->
case lists:keysearch(Val, 2, Args) of
false ->
Key = list_to_atom(lists:concat(["A", length(Args) + 1])),
transl(H, T, [{var, L, Key} | Out], [{Key, Val} | Args], DocRoot);
{value, {Key, _}} ->
transl(H, T, [{var, L, Key} | Out], Args, DocRoot)
end;

transl([H | T], [Token], Out, Args, DocRoot) ->
transl(H, T, [Token | Out], Args, DocRoot).


replace_block({block, Name, [nil, Str1]}, List) ->
case lists:keysearch(Name, 2, List) of
false ->
Str1;
{value, {_, _, [nil, Str2]}} ->
Str2
end;
replace_block(Other, _) ->
Other.


inplace_block({block, _, [nil, Str]}) ->
Str;
inplace_block(Other) ->
Other.



0 comments on commit f84b2a8

Please sign in to comment.