Inherit function for TIr's template rendering
- From:
- Tang Daogang
- Date:
- 2011-02-17 @ 08:11
hi, guys,
I have implemented inheriting function for TIr's template rendering, which
is borrowed from Django.
My design is:
add two tag {: :}, and {[]}, their functions are:
1. put the {: "xxxx" :} to the front of the html file to render. e.g. {:
"base.html" :}. It means when meet this tag, load the base.html on fly;
2. in the base.html file, there are somewhere {[ 'xxxzzz' ]};
3. in the child fragment file, there are somewhere {[ ===== 'xxxzzz'
===== content ]};
4. when render, it will use child fragment file's block xxxzzz's content
to replace base.html's {[ 'xxxzzz' ]}.
My English is not good, so I don't know where describe it clearly.
Wish some help to Tir.
module(..., package.seeall)
local TEMPLATES = APP_DIR + "views/"
local VIEW_ACTIONS = {
['{%'] = function(code)
return code
end,
['{{'] = function(code)
if not code then code = "" end
return ('_result[#_result+1] = %s'):format(code)
end,
['{('] = function(code)
return ([[
if not _children[%s] then
local View = require 'bamboo.view'
_children[%s] = View(%s)
end
_result[#_result+1] = _children[%s](getfenv())
]]):format(code, code, code, code)
end,
['{<'] = function(code)
return ('_result[#_result+1] = http.escapeHTML(%s)'):format(code)
end,
['{['] = function(code)
-- nothing now
return true
end,
['{:'] = function(code, this_page)
local base_page = io.loadFile(TEMPLATES, unseri(code))
local new_page = base_page
for block in new_page:gmatch("({%[[%s_%w%.%-\'\"]+%]})") do
local block_content = block:sub(3, -3):trim()
local this_part = this_page:match('{%[%s*======*%s*' +
block_content + '%s*======*%s+(.+)%s*%]}')
if this_part then
new_page = new_page:gsub('{%[ *' + block_content + ' *%]}',
this_part)
else
new_page = new_page:gsub('{%[ *' + block_content + ' *%]}',
"")
end
end
return new_page
end,
}
local View = Object:extend {
__tag = "Bamboo.View";
__name = 'View';
init = function (self, name)
assert(posix.access(TEMPLATES + name), "Template " + TEMPLATES +
name + " does not exist or wrong permissions.")
if os.getenv('PROD') then
local tmpf = io.loadFile(TEMPLATES, name)
tmpf = self.preprocess(tmpf)
return self.compileView(tmpf, name)
else
return function (params)
local tmpf = io.loadFile(TEMPLATES, name)
assert(tmpf, "Template " + TEMPLATES + name + " does not
exist.")
tmpf = self.preprocess(tmpf)
return self.compileView(tmpf, name)(params)
end
end
end;
preprocess = function(tmpl)
if tmpl:match('{:') then
local block = tmpl:match("(%b{})")
local headtwo = block:sub(1,2)
local block_content = block:sub(3, -3)
assert(headtwo == '{:', 'The inheriate tag must be put in front
of the page.')
local act = VIEW_ACTIONS[headtwo]
return act(block_content, tmpl)
else
return tmpl
end
end;
compileView = function (tmpl, name)
local tmpl = ('%s{}'):format(tmpl)
local code = {'local _result, _children = {}, {}\n'}
for text, block in tmpl:gmatch("([^{]-)(%b{})") do
local act = VIEW_ACTIONS[block:sub(1,2)]
local output = text
if act then
code[#code+1] = '_result[#_result+1] = [[' + text + ']]'
code[#code+1] = act(block:sub(3,-3))
elseif #block > 2 then
code[#code+1] = '_result[#_result+1] = [[' + text + block +
']]'
else
code[#code+1] = '_result[#_result+1] = [[' + text + ']]'
end
end
code[#code+1] = 'return table.concat(_result)'
code = table.concat(code, '\n')
local func, err = loadstring(code, name)
if err then
assert(func, err)
end
return function(context)
assert(context, "You must always pass in a table for context.")
setmetatable(context, {__index=_G})
setfenv(func, context)
return func()
end
end;
}
return View
And one example:
*minindex.html*
{( "header.html" )}
<div class="container">
<!-- Header Part -->
<div id="front">
{( "front.html" )}
</div>
<hr />
<!-- Menu Part -->
<div id="menu" class="column span-24 last">
<!-- 先考虑静态页面 -->
{( "menu.html" )}
</div>
<!-- Content Part -->
<div id="page" class="column span-24 last">
{[ "page" ]}
</div>
<!-- Footer Part -->
<hr />
<div id="footer">
{( "footer.html" )}
</div>
</div>
{( "tail.html" )}
*minipage.html*
{: 'minindex.html' :}
{[ ======== "page" ========
<div id="page_head">
<div id="page_breadcrums">
当面页面:{{page.breadcrums}}
</div>
<div id="page_toolbar">
{( "toolbar.html" )}
</div>
<div style="clear: both;"> </div>
</div>
<div id="page_content">
<div id="page_content_title"> {{page.title}} </div>
<div id="page_content_body">
{{page.content}}
</div>
</div>
<hr/>
<div id="page_children">
{( "children.html" )}
</div>
{( "comment/comment.html" )}
{( "upload/upload.html" )}
]}
this code is very alpha yet, so any suggestions are welcomed.
BR.
--
Nothing is impossible.
Re: [mongrel2] Inherit function for TIr's template rendering
- From:
- Zed A. Shaw
- Date:
- 2011-02-17 @ 16:59
On Thu, Feb 17, 2011 at 04:11:05PM +0800, Tang Daogang wrote:
> hi, guys,
>
> I have implemented inheriting function for TIr's template rendering, which
> is borrowed from Django.
Ah, that's cool.
> My English is not good, so I don't know where describe it clearly.
No problem, I'm very good at English so it's easy to understand you. :-)
I'll take the code you have here and bring it in.
--
Zed A. Shaw
http://zedshaw.com/