add new parsing functions
This commit is contained in:
parent
62ce3a5387
commit
bf1d05fc3c
@ -3,4 +3,6 @@
|
|||||||
```bash
|
```bash
|
||||||
git submodule update --init --recursive
|
git submodule update --init --recursive
|
||||||
git submodule update --remote --recursive
|
git submodule update --remote --recursive
|
||||||
|
|
||||||
|
go build -trimpath -ldflags="-s -w" -o moonshark .
|
||||||
```
|
```
|
||||||
|
@ -418,18 +418,34 @@ local csrf = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
-- ======================================================================
|
-- ======================================================================
|
||||||
-- TEMPLATE RENDER FUNCTION
|
-- TEMPLATE RENDER FUNCTIONS
|
||||||
-- ======================================================================
|
-- ======================================================================
|
||||||
|
|
||||||
_G.render = function(template_str, env)
|
-- Shared utilities
|
||||||
local OPEN_TAG, CLOSE_TAG = "<?", "?>"
|
local __template_util = {
|
||||||
|
escape_html = function(s)
|
||||||
-- Helper functions
|
|
||||||
local function escape_html(s)
|
|
||||||
local entities = {['&']='&', ['<']='<', ['>']='>', ['"']='"', ["'"]='''}
|
local entities = {['&']='&', ['<']='<', ['>']='>', ['"']='"', ["'"]='''}
|
||||||
return (s:gsub([=[["><'&]]=], entities))
|
return (s:gsub([=[["><'&]]=], entities))
|
||||||
end
|
end,
|
||||||
|
|
||||||
|
build_output = function(chunks)
|
||||||
|
return table.concat(chunks)
|
||||||
|
end,
|
||||||
|
|
||||||
|
add_text = function(output, text)
|
||||||
|
if text and #text > 0 then
|
||||||
|
table.insert(output, text)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
|
||||||
|
add_value = function(output, value, escaped)
|
||||||
|
local str = tostring(value or "")
|
||||||
|
table.insert(output, escaped and __template_util.escape_html(str) or str)
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Template processing with code execution
|
||||||
|
_G.render = function(template_str, env)
|
||||||
local function get_line(s, ln)
|
local function get_line(s, ln)
|
||||||
for line in s:gmatch("([^\n]*)\n?") do
|
for line in s:gmatch("([^\n]*)\n?") do
|
||||||
if ln == 1 then return line end
|
if ln == 1 then return line end
|
||||||
@ -443,11 +459,20 @@ _G.render = function(template_str, env)
|
|||||||
return line
|
return line
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Parse template
|
|
||||||
local pos, chunks = 1, {}
|
local pos, chunks = 1, {}
|
||||||
while pos <= #template_str do
|
while pos <= #template_str do
|
||||||
local start, stop = template_str:find(OPEN_TAG, pos, true)
|
local escaped_start = template_str:find("<%?", pos, true)
|
||||||
if not start then
|
local unescaped_start = template_str:find("<!", pos, true)
|
||||||
|
local code_start = template_str:find("<%", pos, true)
|
||||||
|
|
||||||
|
local start, tag_type, open_len
|
||||||
|
if escaped_start and (not unescaped_start or escaped_start < unescaped_start) and (not code_start or escaped_start < code_start) then
|
||||||
|
start, tag_type, open_len = escaped_start, "=", 2
|
||||||
|
elseif unescaped_start and (not code_start or unescaped_start < code_start) then
|
||||||
|
start, tag_type, open_len = unescaped_start, "-", 2
|
||||||
|
elseif code_start then
|
||||||
|
start, tag_type, open_len = code_start, "code", 2
|
||||||
|
else
|
||||||
table.insert(chunks, template_str:sub(pos))
|
table.insert(chunks, template_str:sub(pos))
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
@ -456,11 +481,9 @@ _G.render = function(template_str, env)
|
|||||||
table.insert(chunks, template_str:sub(pos, start-1))
|
table.insert(chunks, template_str:sub(pos, start-1))
|
||||||
end
|
end
|
||||||
|
|
||||||
pos = stop + 1
|
pos = start + open_len
|
||||||
local modifier = template_str:match("^[=-]", pos)
|
local close_tag = tag_type == "=" and "?>" or tag_type == "-" and "!>" or "%>"
|
||||||
if modifier then pos = pos + 1 end
|
local close_start, close_stop = template_str:find(close_tag, pos, true)
|
||||||
|
|
||||||
local close_start, close_stop = template_str:find(CLOSE_TAG, pos, true)
|
|
||||||
if not close_start then
|
if not close_start then
|
||||||
error("Failed to find closing tag at position " .. pos)
|
error("Failed to find closing tag at position " .. pos)
|
||||||
end
|
end
|
||||||
@ -472,7 +495,7 @@ _G.render = function(template_str, env)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local code = template_str:sub(pos, close_start-1)
|
local code = template_str:sub(pos, close_start-1)
|
||||||
table.insert(chunks, {modifier or "code", code, pos})
|
table.insert(chunks, {tag_type, code, pos})
|
||||||
|
|
||||||
pos = close_stop + 1
|
pos = close_stop + 1
|
||||||
if trim_newline and template_str:sub(pos, pos) == "\n" then
|
if trim_newline and template_str:sub(pos, pos) == "\n" then
|
||||||
@ -480,7 +503,6 @@ _G.render = function(template_str, env)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Compile chunks to Lua code
|
|
||||||
local buffer = {"local _tostring, _escape, _b, _b_i = ...\n"}
|
local buffer = {"local _tostring, _escape, _b, _b_i = ...\n"}
|
||||||
for _, chunk in ipairs(chunks) do
|
for _, chunk in ipairs(chunks) do
|
||||||
local t = type(chunk)
|
local t = type(chunk)
|
||||||
@ -504,21 +526,73 @@ _G.render = function(template_str, env)
|
|||||||
end
|
end
|
||||||
table.insert(buffer, "return _b")
|
table.insert(buffer, "return _b")
|
||||||
|
|
||||||
-- Load the compiled code
|
|
||||||
local fn, err = loadstring(table.concat(buffer))
|
local fn, err = loadstring(table.concat(buffer))
|
||||||
if not fn then error(err) end
|
if not fn then error(err) end
|
||||||
|
|
||||||
-- Create execution environment
|
|
||||||
env = env or {}
|
env = env or {}
|
||||||
local runtime_env = setmetatable({}, {__index = function(_, k) return env[k] or _G[k] end})
|
local runtime_env = setmetatable({}, {__index = function(_, k) return env[k] or _G[k] end})
|
||||||
|
|
||||||
setfenv(fn, runtime_env)
|
setfenv(fn, runtime_env)
|
||||||
|
|
||||||
local output_buffer = {}
|
local output_buffer = {}
|
||||||
fn(tostring, escape_html, output_buffer, 0)
|
fn(tostring, __template_util.escape_html, output_buffer, 0)
|
||||||
return table.concat(output_buffer)
|
return table.concat(output_buffer)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Named placeholder processing
|
||||||
|
_G.parse = function(template_str, env)
|
||||||
|
local pos, output = 1, {}
|
||||||
|
env = env or {}
|
||||||
|
|
||||||
|
while pos <= #template_str do
|
||||||
|
local escaped_start, escaped_end, escaped_name = template_str:find("<%?%s*([%w_]+)%s*%?>", pos)
|
||||||
|
local unescaped_start, unescaped_end, unescaped_name = template_str:find("<!%s*([%w_]+)%s*!>", pos)
|
||||||
|
|
||||||
|
local next_pos, placeholder_end, name, escaped
|
||||||
|
if escaped_start and (not unescaped_start or escaped_start < unescaped_start) then
|
||||||
|
next_pos, placeholder_end, name, escaped = escaped_start, escaped_end, escaped_name, true
|
||||||
|
elseif unescaped_start then
|
||||||
|
next_pos, placeholder_end, name, escaped = unescaped_start, unescaped_end, unescaped_name, false
|
||||||
|
else
|
||||||
|
__template_util.add_text(output, template_str:sub(pos))
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
__template_util.add_text(output, template_str:sub(pos, next_pos - 1))
|
||||||
|
__template_util.add_value(output, env[name], escaped)
|
||||||
|
pos = placeholder_end + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
return __template_util.build_output(output)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Indexed placeholder processing
|
||||||
|
_G.iparse = function(template_str, values)
|
||||||
|
local pos, output, value_index = 1, {}, 1
|
||||||
|
values = values or {}
|
||||||
|
|
||||||
|
while pos <= #template_str do
|
||||||
|
local escaped_start, escaped_end = template_str:find("<%?>", pos, true)
|
||||||
|
local unescaped_start, unescaped_end = template_str:find("<!>", pos, true)
|
||||||
|
|
||||||
|
local next_pos, placeholder_end, escaped
|
||||||
|
if escaped_start and (not unescaped_start or escaped_start < unescaped_start) then
|
||||||
|
next_pos, placeholder_end, escaped = escaped_start, escaped_end, true
|
||||||
|
elseif unescaped_start then
|
||||||
|
next_pos, placeholder_end, escaped = unescaped_start, unescaped_end, false
|
||||||
|
else
|
||||||
|
__template_util.add_text(output, template_str:sub(pos))
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
__template_util.add_text(output, template_str:sub(pos, next_pos - 1))
|
||||||
|
__template_util.add_value(output, values[value_index], escaped)
|
||||||
|
pos = placeholder_end + 1
|
||||||
|
value_index = value_index + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
return __template_util.build_output(output)
|
||||||
|
end
|
||||||
|
|
||||||
-- ======================================================================
|
-- ======================================================================
|
||||||
-- PASSWORD MODULE
|
-- PASSWORD MODULE
|
||||||
-- ======================================================================
|
-- ======================================================================
|
||||||
|
Loading…
x
Reference in New Issue
Block a user