1 /*
2  * Hunt - A high-level D Programming Language Web framework that encourages rapid development and clean, pragmatic design.
3  *
4  * Copyright (C) 2015-2019, HuntLabs
5  *
6  * Website: https://www.huntlabs.net/
7  *
8  * Licensed under the Apache-2.0 License.
9  *
10  */
11 
12 module hunt.framework.view.Template;
13 
14 private
15 {
16     import std.meta;
17     import std.traits;
18 
19     import hunt.framework.view.Render;
20     import hunt.framework.view.Lexer;
21     import hunt.framework.view.Parser;
22     import hunt.framework.view.Uninode;
23     import hunt.framework.view.ast;
24 }
25 
26 struct TemplateConfig
27 {
28     string exprOpBegin  = "{{";
29     string exprOpEnd    = "}}";
30     string stmtOpBegin  = "{%";
31     string stmtOpEnd    = "%}";
32     string cmntOpBegin  = "{#";
33     string cmntOpEnd    = "#}";
34     string cmntOpInline = "##!";
35     string stmtOpInline = "#!";
36 }
37 
38 TemplateNode loadData(TemplateConfig config = defaultConfig)(string tmpl)
39 {
40     alias TemplateLexer = Lexer!(
41                             config.exprOpBegin,
42                             config.exprOpEnd,
43                             config.stmtOpBegin,
44                             config.stmtOpEnd,
45                             config.cmntOpBegin,
46                             config.cmntOpEnd,
47                             config.stmtOpInline,
48                             config.cmntOpInline
49                         );
50 
51     Parser!TemplateLexer parser;
52     return parser.parseTree(tmpl);
53 }
54 
55 TemplateNode loadFile(TemplateConfig config = defaultConfig)(string path)
56 {
57     alias TemplateLexer = Lexer!(
58                             config.exprOpBegin,
59                             config.exprOpEnd,
60                             config.stmtOpBegin,
61                             config.stmtOpEnd,
62                             config.cmntOpBegin,
63                             config.cmntOpEnd,
64                             config.stmtOpInline,
65                             config.cmntOpInline
66                         );
67 
68     Parser!TemplateLexer parser;
69     return parser.parseTreeFromFile(path);
70 }
71 
72 string render(T...)(TemplateNode tree)
73 {
74     alias Args = AliasSeq!T;
75     alias Idents = staticMap!(Ident, T);
76 
77     auto render = new Render(tree);
78 
79     auto data = UniNode.emptyObject();
80 
81     foreach (i, arg; Args)
82     {
83         static if (isSomeFunction!arg)
84             render.registerFunction!arg(Idents[i]);
85         else
86             data[Idents[i]] = arg.serialize;
87     }
88 
89     return render.render(data.serialize);
90 }
91 
92 string renderData(T...)(string tmpl)
93 {
94     static if (T.length > 0 && is(typeof(T[0]) == TemplateConfig))
95         return render!(T[1 .. $])(loadData!(T[0])(tmpl));
96     else
97         return render!(T)(loadData!defaultConfig(tmpl));
98 }
99 
100 string renderFile(T...)(string path)
101 {
102     static if (T.length > 0 && is(typeof(T[0]) == TemplateConfig))
103         return render!(T[1 .. $])(loadFile!(T[0])(path));
104     else
105         return render!(T)(loadFile!defaultConfig(path));
106 }
107 
108 
109 
110 void print(TemplateNode tree)
111 {
112     auto printer = new Printer;
113     tree.accept(printer);
114 }
115 
116 private:
117 
118 enum defaultConfig = TemplateConfig.init;
119 
120 template Ident(alias A)
121 {
122     enum Ident = __traits(identifier, A);
123 }