1 /**
2  * Temple (C) Dylan Knutson, 2013, distributed under the:
3  * Boost Software License - Version 1.0 - August 17th, 2003
4  *
5  * Permission is hereby granted, free of charge, to any person or organization
6  * obtaining a copy of the software and accompanying documentation covered by
7  * this license (the "Software") to use, reproduce, display, distribute,
8  * execute, and transmit the Software, and to prepare derivative works of the
9  * Software, and to permit third-parties to whom the Software is furnished to
10  * do so, all subject to the following:
11  *
12  * The copyright notices in the Software and this entire statement, including
13  * the above license grant, this restriction and the following disclaimer,
14  * must be included in all copies of the Software, in whole or in part, and
15  * all derivative works of the Software, unless such copies or derivative
16  * works are solely in the form of machine-executable object code generated by
17  * a source language processor.
18  */
19 
20 module temple.temple;
21 
22 private import
23 	temple.util,
24 	temple.delims,
25 	temple.func_string_gen;
26 
27 public import
28 	temple.temple,
29 	temple.temple_context,
30 	temple.output_stream,
31 	temple.vibe;
32 
33 /**
34  * Temple
35  * Main template for generating Temple functions
36  */
37 template Temple(string __TempleString, __Filter = void)
38 {
39 	alias Temple = Temple!(__TempleString, "InlineTemplate", __Filter);
40 }
41 
42 template Temple(
43 	string __TempleString,
44 	string __TempleName,
45 	__Filter = void)
46 {
47 	// __TempleString: The template string to compile
48 	// __TempleName: The template's file name, or 'InlineTemplate'
49 	// __Filter: FP for the rendered template
50 
51 	// Is a Filter present?
52 	enum __TempleHasFP = !is(__Filter == void);
53 
54 	// Needs to be kept in sync with the param name of the Filter
55 	// passed to Temple
56 	enum __TempleFilterIdent = __TempleHasFP ? "__Filter" : "";
57 
58 	// Generates the actual function string, with the function name being
59 	// `TempleFunc`.
60 	const __TempleFuncStr = __temple_gen_temple_func_string(
61 		__TempleString,
62 		__TempleName,
63 		__TempleFilterIdent);
64 
65 	//pragma(msg, temple_fun_str);
66 
67 	#line 411 "TempleFunc"
68 	mixin(__TempleFuncStr);
69 	#line 413 "src/temple/temple.d"
70 
71 	static if(__TempleHasFP) {
72 		alias Temple = TempleFunc!__Filter;
73 	}
74 	else {
75 		alias Temple = TempleFunc;
76 	}
77 }
78 
79 /**
80  * TempleFile
81  * Compiles a file on the disk into a Temple render function
82  * Takes an optional Filter
83  */
84 template TempleFile(string template_file, Filter = void)
85 {
86 	pragma(msg, "Compiling ", template_file, "...");
87 	alias TempleFile = Temple!(import(template_file), template_file, Filter);
88 }
89 
90 /**
91  * TempleLayout
92  * Sets up a template to be used as an enclosing layout for a nested Temple
93  * template
94  * Takes an optional Filter
95  */
96 template TempleLayout(string template_string, Filter = void)
97 {
98 	alias layout_renderer = Temple!(template_string, Filter);
99 	alias TempleLayout = TempleLayoutImpl!layout_renderer;
100 }
101 
102 /**
103  * TempleLayout
104  * Sets up a file to be used as an enclosing layout for a nested Temple
105  * template
106  * Takes an optional Filter
107  */
108 template TempleLayoutFile(string template_file, Filter = void)
109 {
110 	alias layout_renderer = TempleFile!(template_file, Filter);
111 	alias TempleLayoutFile = TempleLayoutImpl!layout_renderer;
112 }
113 
114 /*
115  * Implementation for a Temple layout function
116  */
117 package void TempleLayoutImpl(alias layout_renderer)(
118 	OutputStream buff,
119 	TempleFuncType* temple_func,
120 	TempleContext context = null)
121 {
122 	// always ensure that a context is present
123 	if(context is null)
124 	{
125 		context = new TempleContext();
126 	}
127 
128 	auto old_partial = context.partial;
129 	context.partial = temple_func;
130 	scope(exit)
131 	{
132 		context.partial = old_partial;
133 	}
134 
135 	layout_renderer(buff, context);
136 }
137 
138 /**
139  * TempleFilter
140  * Partial application of a Filter to be used with the Temple* family of templates
141  */
142 template TempleFilter(Filter) {
143 	template Temple(ARGS...) {
144 		alias Temple = .Temple!(ARGS, Filter);
145 	}
146 
147 	template TempleFile(ARGS...) {
148 		alias TempleFile = .TempleFile!(ARGS, Filter);
149 	}
150 
151 	template TempleLayout(ARGS...) {
152 		alias TempleLayout = .TempleLayout!(ARGS, Filter);
153 	}
154 
155 	template TempleLayoutFile(ARGS...) {
156 		alias TempleLayoutFile = .TempleLayoutFile!(ARGS, Filter);
157 	}
158 }
159 
160 /**
161  * TempleFuncType
162  * TempleLayoutFuncType
163  *
164  * Function signatures for a Temple template, and layout template,
165  * which are `void function(OutputStream, TempleContext = null)` and
166  *           `void function(OutputStream, TempleFuncType*, TempleContext = null)`
167  * respectivly
168  */
169 alias TempleFuncType = typeof(Temple!("", ""));
170 alias TempleLayoutFuncType = typeof(TempleLayoutImpl!(Temple!("", "")));
171 
172 /**
173  * Helper functions for quicly rendering a template as a string
174  */
175 string templeToString(TempleFuncType* func, TempleContext context = null)
176 {
177 	auto accum = new AppenderOutputStream;
178 	(*func)(accum, context);
179 	return accum.data;
180 }
181 
182 string templeToString(TempleLayoutFuncType* layout, TempleFuncType* partial, TempleContext context = null)
183 {
184 	auto accum = new AppenderOutputStream;
185 	(*layout)(accum, partial, context);
186 	return accum.data;
187 }
188