Skip to content

Commit 7b4a05a

Browse files
committed
update readme fix error on engine loading and bump version to 0.1.7
1 parent 4f28864 commit 7b4a05a

File tree

2 files changed

+28
-189
lines changed

2 files changed

+28
-189
lines changed

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
PROJECT = aihtml
22
PROJECT_DESCRIPTION = html tool for productions from ailink.io
3-
PROJECT_VERSION = 0.1.6
3+
PROJECT_VERSION = 0.1.7
44

55
ERLC_OPTS = -Werror +debug_info +warn_export_vars +warn_shadow_vars +warn_obsolete_guard
66
DEPS = ailib
77

8-
dep_ailib = git https://github.com/DavidAlphaFox/ailib.git tag-0.1.6
8+
dep_ailib = git https://github.com/DavidAlphaFox/ailib.git tag-0.2.0
99

1010
include erlang.mk

README.md

Lines changed: 26 additions & 187 deletions
Original file line numberDiff line numberDiff line change
@@ -39,213 +39,52 @@ included in the code path of projects that need it.
3939
The simplest example involves using a string template and a context from the REPL.
4040

4141
Ctx = maps:from_list([{<<"planet">>, <<"World!">>}]).
42-
{module,Mod} = ai_mustache_compiler:compile(simple,<<"Hello {{planet}}">>).
43-
Mod:render(Ctx).
42+
{IR,Partials} = ai_mustache_parser:parse(<<"Hello {{planet}}">>).
43+
ai_mustache_runner:render({IR,Partials},Ctx).
44+
4445

4546

4647
In line 1 we created a context that contains a value bound to the `planet`
47-
tag. In line 2 we generate a template module which will be named `simple_ai_mustache`.
48+
tag. In line 2 we generate some IR code of the template.
4849
In line 3 we render then template by passing in the context.
4950

5051

51-
### Two-File Example
52-
53-
54-
A more complex example consists of two files: the view and the template. The
55-
view (logic) file is an Erlang module (simple.erl):
56-
57-
-module(simple).
58-
-compile(export_all).
59-
value() -> 10000.
60-
get_value(<<"name">>,_Ctx)-> "Tome";
61-
get_value(<<"value>>,_Ctx)-> value() ;
62-
get_value(<<"taxed_value">>,_Ctx)->
63-
value() - (value() * 0.4);
64-
get_value(<<"in_ca">>,_Ctx)-> true.
65-
66-
67-
In the view we define functions that will be called by the template. The names
68-
of the functions correspond to the tag names that will be used in the
69-
template. Some functions reference others, some return values, and some return
70-
only booleans.
71-
72-
The template file (simple.mustache) looks like so:
73-
74-
Hello {{name}}
75-
You have just won ${{value}}!
76-
{{#in_ca}}
77-
Well, ${{taxed_value}}, after taxes.
78-
{{/in_ca}}
79-
80-
Notice that the template references the functions in the view module. The
81-
return values from the view dictate how the template will be rendered. To get
82-
the HTML output, make sure the `simple.beam` bytecode file is in your code
83-
path and call the following function:
84-
85-
mustache:render(simple)
86-
87-
This tells Mustache to use the `simple` view and to look for a template named
88-
`simple.mustache` in the same directory as the `simple.beam` bytecode file. If
89-
all goes well, it returns the rendered HTML:
90-
91-
Hello Tom
92-
You have just won $10000!
93-
Well, $6000.00, after taxes.
94-
95-
96-
97-
98-
### The Power of Context
99-
100-
101-
You will often want to provide additional data to your template and view. You
102-
can do this by passing in an initial context to the render function. During
103-
rendering, tag lookups always hit the context first before looking for a view
104-
function. In this way, the context can be used to override view functions.
105-
Using the same template and view as above, we can replace the name tag with
106-
different data by constructing a context and passing it to `render`:
107-
108-
109-
Ctx = map:from_list([{<<"name">>, "Chris"}]).
110-
{module,Mod} = ai_mustache_compiler:compile(simple,Body).
111-
Mod:render(Ctx).
112-
113-
This will produce the following output:
114-
115-
Hello Chris
116-
You have just won $10000!
117-
Well, $6000.00, after taxes.
118-
119-
The context is also accessible from view functions, making it easy to pass in
120-
initialization data. Consider a case where we want to pass in a user ID:
121-
122-
Ctx = map:from_list([{id, 42}])
123-
124-
View functions can get access to the context by accepting a single argument:
125-
126-
name(Ctx) ->
127-
...
128-
129-
Now when this function is called, it will be handed the context. In order to
130-
fetch data from the context, use `mustache:get/2`:
131-
132-
name(Ctx) ->
133-
Id = maps:get(id, Ctx, undefined),
134-
...
135-
136-
If the requested key does not exist in the context, the atom `undefined` will be returned.
137-
52+
### Using as View Engine
13853

139-
Tag Types
140-
---------
54+
please refer [examples/complex.erl](https://github.com/DavidAlphaFox/aihtml/blob/master/examples/complex.erl)
14155

142-
Tags are indicated by the double mustaches. `{{name}}` is a tag. Let's talk
143-
about the different types of tags.
56+
The engine will start a process named `ai_mustache_loader` to manage the templates under given directory.
14457

145-
### Variables
58+
If a template is a parials, the filename must be prefixed with underscore.
14659

147-
The most basic tag is the variable. A `{{name}}` tag in a basic template will
148-
try to call the `name` function on your view. By default a variable "miss"
149-
returns an empty string.
60+
The engine can load the templates without `ai_mustche:prepare`, but I recommand that call this fucation once after the tmeplate engine is started. Because the engine use only one `gen_server` to load template which may be very slow when the request is arrived.
15061

151-
All variables are HTML escaped by default. If you want to return unescaped
152-
HTML, use the triple mustache: `{{{name}}}`.
15362

154-
### Boolean Sections
15563

156-
A section begins with a pound and ends with a slash. That is,
157-
`{{#person}}` begins a "person" section while `{{/person}}` ends it.
64+
## Erlang版Mustache编译器
15865

159-
If the `person` method exists and calling it returns `false`, the HTML
160-
between the pound and slash will not be displayed.
66+
Mustache是一款和框架无关的模板引擎系统,着重于将逻辑和视图分开。因此Mustache模板甚至没有任何内嵌的逻辑,因此可以跨多个语言使用。
16167

162-
If the `person` method exists and calling it returns `true`, the HTML
163-
between the pound and slash will be rendered and displayed.
68+
当前该版本是一个比较早期的版本,在内部虽然得到部分使用,但依然存在一定量的Bug,请谨慎使用
16469

16570

166-
### List Sections
71+
### 最简单的例子
16772

168-
List sections are syntactically identical to boolean sections in that they
169-
begin with a pound and end with a slash. The difference, however, is in the
170-
view: if the function called returns a list, the section is repeated as the
171-
list is iterated over.
73+
这个例子只是在Erlang的REPL中使用一个字符串和一个简单的context。
17274

173-
Each item in the enumerable is expected to be a map that will then become the
174-
context of the corresponding iteration. In this way we can construct loops.
175-
176-
For example, imagine this template:
177-
178-
{{#repo}}
179-
<b>{{name}}</b>
180-
{{/repo}}
181-
182-
And this view code:
183-
184-
repo() ->
185-
[map:from_list([{<<"name">>, Name}]) || Name <- ["Tom", "Chris", "PJ"]].
186-
187-
When rendered, our view will contain a list of each of the names in the source list. When left the section, the context will be restored, the view will not contain the names anymore.
188-
189-
### Inverted Sections
190-
An inverted section begins with a caret (hat) and ends with a slash. That is {{^person}} begins a "person" inverted section while {{/person}} ends it.
191-
192-
While sections can be used to render text one or more times based on the value of the key, inverted sections may render text once based on the inverse value of the key. That is, they will be rendered if the key doesn't exist, is `false`, or is an empty list `[]`.
193-
194-
### Comments
195-
196-
Comments begin with a bang and are ignored. The following template:
197-
198-
<h1>Today{{! ignore me }}.</h1>
199-
200-
Will render as follows:
201-
202-
<h1>Today.</h1>
203-
204-
### Partials
205-
206-
Partials begin with a greater than sign, like {{> box}}.
207-
208-
Partials are rendered at runtime (as opposed to compile time), so recursive partials are possible. Just avoid infinite loops.
209-
210-
They also inherit the calling context.
211-
212-
In this way you may want to think of partials as includes, imports, template expansion, nested templates, or subtemplates, even though those aren't literally the case here.
213-
214-
For example, this template and partial:
215-
216-
base.mustache:
217-
218-
<h2>Names</h2>
219-
{{#names}}
220-
{{>_user}}
221-
{{/names}}
222-
223-
user.mustache:
75+
Ctx = maps:from_list([{<<"planet">>, <<"World!">>}]).
76+
{IR,Partials} = ai_mustache_parser:parse(<<"Hello {{planet}}">>).
77+
ai_mustache_runner:render({IR,Partials},Ctx).
22478

225-
<strong>{{name}}</strong>
226-
Can be thought of as a single, expanded template:
227-
228-
<h2>Names</h2>
229-
{{#names}}
230-
<strong>{{name}}</strong>
231-
{{/names}}
232-
233-
In Erlang REPL
234-
235-
{ok,BaseBody} = file:read_file("base.mustache").
236-
{ok,UserBody} = file:read_file("user.mustache").
237-
{module,UserMod} = ai_mustache_compiler:compile(user,UserBody).
238-
{module,BaseMod} = ai_mustache_compiler:compile(base,BaseBody).
239-
BaseMod:render(#{<<"_user">> => UserMod}).
240-
241-
### not support
242-
243-
aihtml doesn't support `Set Delimiter`.
244-
245-
### todo
246-
247-
`template manager`
79+
80+
第一行创建了一个非常简单的context,其中包行了 `planet` 标签。
81+
第二行生成了模板的IR代码。而在第三行则使用IR代码和前面的context将木板进行了渲染。
24882

249-
template manger will manage all templates in your project, auto compile all templates and default context to handle partial template rendering.
83+
### 做为视图引擎
84+
请参考[examples/complex.erl](https://github.com/DavidAlphaFox/aihtml/blob/master/examples/complex.erl)
25085

86+
视图引擎将启动一个叫`ai_mustache_loader`的进行对指定目录下的所有模板进行管理
25187

88+
如果文件前面有一个`_`下划线,引擎则会认为这个文件为子模板。虽然引擎可以不使用`ai_mustche:prepare`进行预热,也可以按照需要逐个编译模板。
89+
因为该引擎只使用了一个`gen_server`和两个ets表来管理所有的模板,所以当请求到达的时候才去遍历模板,并加载会比较缓慢,因此建议在引擎启动后立刻执行
90+
`ai_mustche:prepare`进行预热,同时也可发现不正确的模板或引擎问题。

0 commit comments

Comments
 (0)