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.algo.Functions;
13 
14 private
15 {
16     import hunt.framework.view.algo.Wrapper;
17     import hunt.framework.view.Exception : assertTemplate = assertTemplateException, TemplateRenderException;
18     import hunt.framework.view.Uninode;
19 
20     import hunt.logging;
21 
22     import std.array : array;
23     import std.algorithm : map;   
24     import std.functional : toDelegate;
25     import std.format : fmt = format;
26     import std.conv;
27 
28     import std.range : iota;
29     import std.string; 
30 }
31 
32 // dfmt off
33 Function[string] globalFunctions()
34 {
35     return cast(immutable)
36         [
37             "range": toDelegate(&range),
38             "length": wrapper!length,
39             "count": wrapper!length,
40             "namespace": wrapper!namespace,
41             "date": wrapper!date,
42             "url": wrapper!url,
43             "int": wrapper!Int,
44             "split": wrapper!split,
45             "string": wrapper!String,
46             "trans":toDelegate(&trans),
47             "format" : toDelegate(&doFormat)
48         ];
49 }
50 // dfmt on
51 
52 /**
53  * "a, b, c"  => ["a", "b", "c"]
54  */
55 UniNode split(UniNode str, UniNode seperator = UniNode(",") ) { 
56     version(HUNT_VIEW_DEBUG) {
57         tracef("params: %s,  kind: %s", str.toString(), str.kind());
58         tracef("seperator: %s,  kind: %s", seperator.toString(), seperator.kind());
59     }
60 
61     if(str.kind() != UniNode.Kind.text && seperator.kind() != UniNode.Kind.text) {
62         assertTemplate(0, "Only string supported");
63         return UniNode("");
64     }
65 
66     string separator = seperator.get!string();
67     string value = str.get!string;
68     string[] items = std..string.split(value, separator);
69     UniNode[] arr = items.map!(a => UniNode(a.strip())).array;
70 
71     return UniNode(arr);
72 }
73 
74 
75 UniNode range(UniNode params)
76 {
77 
78     assertTemplate(params.kind == UniNode.Kind.object, "Non object params");
79     assertTemplate(cast(bool)("varargs" in params), "Missing varargs in params");
80 
81     if (params["varargs"].length > 0)
82     {
83         auto length = params["varargs"][0].get!long;
84         auto arr = iota(length).map!(a => UniNode(a)).array;
85         return UniNode(arr);
86     }
87 
88     assertTemplate(0);
89     assert(0);
90 }
91 
92 long length(UniNode value)
93 {
94     switch (value.kind) with (UniNode.Kind)
95     {
96     case array:
97     case object:
98         return value.length;
99     case text:
100         return value.get!string.length;
101     default:
102         assertTemplate(0, "Object of type `%s` has no length()".fmt(value.kind));
103     }
104     assert(0);
105 }
106 
107 int Int(UniNode value)
108 {
109     switch (value.kind) with (UniNode.Kind)
110     {
111     case integer:
112         return cast(int)(value.get!long);
113     case uinteger:
114         return cast(int)(value.get!ulong);
115     case boolean:
116         return value.get!bool ? 1 : 0;
117     case text:
118         return value.get!string
119             .to!int;
120     default:
121         assertTemplate(0, "Object of type `%s` has no int()".fmt(value.kind));
122     }
123     assert(0);
124 }
125 
126 string String(UniNode value)
127 {
128     switch (value.kind) with (UniNode.Kind)
129     {
130     case integer:
131         return to!string(value.get!long);
132     case uinteger:
133         return to!string(value.get!ulong);
134     case boolean:
135         return value.get!bool ? "true" : "false";
136     case text:
137         return value.get!string;
138     default:
139         assertTemplate(0, "Object of type `%s` has no string()".fmt(value.kind));
140     }
141     assert(0);
142 }
143 
144 UniNode namespace(UniNode kwargs)
145 {
146     return kwargs;
147 }
148 
149 ///dummy
150 UniNode trans(UniNode node)
151 {
152     return UniNode(null);
153 }
154 
155 ///dummy
156 string date(string format, long timestamp)
157 {
158     return null;
159 }
160 ///dummy
161 string url(string format, string d)
162 {
163     return null;
164 }
165 
166 UniNode doFormat(UniNode args)
167 {
168     import hunt.framework.util.Formatter;
169     import hunt.framework.util.uninode.Serialization;
170 
171     if ("varargs" in args)
172     {
173         args = args["varargs"];
174     }
175 
176     if (args.kind == UniNode.Kind.array)
177     {
178         if (args.length == 1)
179         {
180             return args[0];
181         }
182         else if (args.length > 1)
183         {
184             string msg = args[0].get!string;
185             UniNode[] params;
186             for (int i = 1; i < args.length; i++)
187             {
188                 params ~= args[i];
189             }
190 
191             return UniNode(StrFormat(msg, uniNodeToJSON(UniNode(params))));
192         }
193     }
194     throw new TemplateRenderException("unsupport param : " ~ args.toString);
195 }