alpha p4
This commit is contained in:
1
TODO
1
TODO
@@ -1,3 +1,2 @@
|
||||
Add an interval element
|
||||
Add a way to pass data to sites on load via fes.bus
|
||||
Fire emoji default favicon
|
||||
|
||||
480
core/builtin.lua
480
core/builtin.lua
@@ -3,24 +3,29 @@ local std = require("core.std")
|
||||
local M = {}
|
||||
M.__index = M
|
||||
|
||||
local function encode(str)
|
||||
return str:gsub("([^%w%-%_%.%~])", function(c)
|
||||
return string.format("%%%02X", string.byte(c)) end) end
|
||||
|
||||
function M.fes(header, footer)
|
||||
local config = {}
|
||||
local site_config = {}
|
||||
local config = {}
|
||||
local site_config = {}
|
||||
local fes_mod = package.loaded.fes
|
||||
if fes_mod and fes_mod.config then
|
||||
config = fes_mod.config
|
||||
if config.site then
|
||||
site_config = config.site
|
||||
end
|
||||
end
|
||||
|
||||
local fes_mod = package.loaded.fes
|
||||
if fes_mod and fes_mod.config then
|
||||
config = fes_mod.config
|
||||
if config.site then
|
||||
site_config = config.site
|
||||
end
|
||||
end
|
||||
local raw_favicon = site_config.favicon or [[<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><text y=".9em" font-size="90">🔥</text></svg>]]
|
||||
|
||||
local self = {
|
||||
version = site_config.version or "",
|
||||
title = site_config.title or "Document",
|
||||
copyright = site_config.copyright or "© The Copyright Holder",
|
||||
favicon = "/image/favicon.ico",
|
||||
header = header or [[
|
||||
local self = {
|
||||
version = site_config.version or "",
|
||||
title = site_config.title or "Document",
|
||||
copyright = site_config.copyright or "© The Copyright Holder",
|
||||
favicon = "data:image/svg+xml," .. encode(raw_favicon),
|
||||
header = header or [[
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
@@ -29,357 +34,71 @@ function M.fes(header, footer)
|
||||
<link rel="icon" href="{{FAVICON}}">
|
||||
<title>{{TITLE}}</title>
|
||||
<style>
|
||||
html, body {
|
||||
min-height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: #0f1113;
|
||||
color: #e6eef3;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
||||
line-height: 1.5;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
body {
|
||||
padding: 36px;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 830px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.container > *:not(.banner) {
|
||||
margin: 28px 0;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-weight: 600;
|
||||
margin: 0 0 12px 0;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 40px;
|
||||
margin-bottom: 20px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 32px;
|
||||
margin: 26px 0 14px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 26px;
|
||||
margin: 22px 0 12px;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 20px;
|
||||
margin: 18px 0 10px;
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 16px;
|
||||
margin: 16px 0 8px;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 14px;
|
||||
margin: 14px 0 6px;
|
||||
color: #9aa6b1;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 14px 0;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #68a6ff;
|
||||
text-decoration: none;
|
||||
transition: color .15s ease, text-decoration-color .15s ease;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
color: #dfe9ee;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
summary {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
details {
|
||||
background: #1a1c20;
|
||||
border: 1px solid rgba(255,255,255,.06);
|
||||
border-radius: 4px;
|
||||
padding: 14px 16px;
|
||||
margin: 16px 0;
|
||||
}
|
||||
|
||||
details summary {
|
||||
list-style: none;
|
||||
font-weight: 600;
|
||||
color: #e6eef3;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
details summary::-webkit-details-marker {
|
||||
display: none;
|
||||
}
|
||||
|
||||
details summary::before {
|
||||
content: "▸";
|
||||
margin-right: 8px;
|
||||
transition: transform .15s ease;
|
||||
color: #68a6ff;
|
||||
}
|
||||
|
||||
details[open] summary::before {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
summary::after {
|
||||
content: "Expand";
|
||||
margin-left: auto;
|
||||
font-size: 13px;
|
||||
color: #9aa6b1;
|
||||
}
|
||||
|
||||
details[open] summary::after {
|
||||
content: "Collapse";
|
||||
}
|
||||
|
||||
details > *:not(summary) {
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.note, pre, code {
|
||||
background: #1a1c20;
|
||||
border: 1px solid rgba(255,255,255,.06);
|
||||
}
|
||||
|
||||
.note {
|
||||
padding: 20px;
|
||||
border-radius: 4px;
|
||||
background: #1a1c20;
|
||||
border: 1px solid rgba(255,255,255,.06);
|
||||
margin: 28px 0;
|
||||
color: #dfe9ee;
|
||||
}
|
||||
|
||||
.note strong {
|
||||
color: #f0f6f8;
|
||||
}
|
||||
|
||||
.muted {
|
||||
color: #9aa6b1;
|
||||
}
|
||||
|
||||
.lead {
|
||||
font-size: 15px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.callout {
|
||||
display: block;
|
||||
margin: 12px 0;
|
||||
}
|
||||
|
||||
.small {
|
||||
font-size: 13px;
|
||||
color: #9aa6b1;
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.highlight {
|
||||
font-weight: 700;
|
||||
color: #cde7ff;
|
||||
}
|
||||
|
||||
ul, ol {
|
||||
margin: 14px 0;
|
||||
padding-left: 26px;
|
||||
}
|
||||
|
||||
.tl {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, 200px);
|
||||
gap: 15px;
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
justify-content: start;
|
||||
}
|
||||
|
||||
ul.tl li {
|
||||
padding: 10px;
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
li {
|
||||
margin: 6px 0;
|
||||
}
|
||||
|
||||
code {
|
||||
padding: 3px 7px;
|
||||
border-radius: 3px;
|
||||
font-family: "SF Mono", Monaco, "Cascadia Code", "Roboto Mono", Consolas, "Courier New", monospace;
|
||||
font-size: .9em;
|
||||
color: #cde7ff;
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: 20px;
|
||||
border-radius: 4px;
|
||||
margin: 14px 0;
|
||||
overflow-x: auto;
|
||||
font-family: "SF Mono", Monaco, "Cascadia Code", "Roboto Mono", Consolas, "Courier New", monospace;
|
||||
font-size: 14px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
pre code {
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
border-left: 3px solid #68a6ff;
|
||||
padding-left: 18px;
|
||||
margin: 14px 0;
|
||||
color: #dfe9ee;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 0;
|
||||
border-top: 1px solid rgba(255,255,255,.1);
|
||||
margin: 26px 0;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
border-radius: 4px;
|
||||
margin: 14px 0;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin: 14px 0;
|
||||
}
|
||||
|
||||
th, td {
|
||||
padding: 12px 16px;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid rgba(255,255,255,.06);
|
||||
}
|
||||
|
||||
th {
|
||||
background: #1a1c20;
|
||||
font-weight: 600;
|
||||
color: #f0f6f8;
|
||||
}
|
||||
|
||||
tr:hover {
|
||||
background: rgba(255,255,255,.02);
|
||||
}
|
||||
|
||||
.divider {
|
||||
margin: 26px 0;
|
||||
height: 1px;
|
||||
background: rgba(255,255,255,.1);
|
||||
}
|
||||
|
||||
.section {
|
||||
margin-top: 36px;
|
||||
}
|
||||
|
||||
.links {
|
||||
margin: 12px 0;
|
||||
}
|
||||
|
||||
.links a {
|
||||
display: inline-block;
|
||||
margin: 0 14px 6px 0;
|
||||
}
|
||||
|
||||
strong, b {
|
||||
font-weight: 600;
|
||||
color: #f0f6f8;
|
||||
}
|
||||
|
||||
em, i {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.note {
|
||||
padding: 20px;
|
||||
border-radius: 4px;
|
||||
background: #1a1c20;
|
||||
border: 1px solid rgba(255,255,255,.06);
|
||||
margin: 28px 0;
|
||||
color: #dfe9ee;
|
||||
}
|
||||
|
||||
.center {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.banner {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
background: #1a1c20;
|
||||
padding: 20px;
|
||||
border: 1px solid rgba(255,255,255,.06);
|
||||
border-bottom-right-radius: 8px;
|
||||
border-bottom-left-radius: 8px;
|
||||
color: #e6eef3;
|
||||
margin: -36px 0 28px 0;
|
||||
box-shadow: 0 0.2em 0.6em rgba(0,0,0,.4);
|
||||
}
|
||||
|
||||
.nav {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.nav a {
|
||||
color: #cde7ff;
|
||||
}
|
||||
|
||||
.footer {
|
||||
background: #1a1c20;
|
||||
padding: 20px 0;
|
||||
border-top: 1px solid rgba(255,255,255,.1);
|
||||
font-size: 14px;
|
||||
color: #d4dde3;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 24px;
|
||||
margin-top: 28px !important;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
html, body { min-height: 100%; margin: 0; padding: 0; background: #0f1113; color: #e6eef3; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; line-height: 1.5; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
|
||||
body { padding: 36px; }
|
||||
.container { max-width: 830px; margin: 0 auto; }
|
||||
.container > *:not(.banner) { margin: 28px 0; }
|
||||
h1, h2, h3, h4, h5, h6 { font-weight: 600; margin: 0 0 12px 0; }
|
||||
h1 { font-size: 40px; margin-bottom: 20px; font-weight: 700; }
|
||||
h2 { font-size: 32px; margin: 26px 0 14px; }
|
||||
h3 { font-size: 26px; margin: 22px 0 12px; }
|
||||
h4 { font-size: 20px; margin: 18px 0 10px; }
|
||||
h5 { font-size: 16px; margin: 16px 0 8px; }
|
||||
h6 { font-size: 14px; margin: 14px 0 6px; color: #9aa6b1; }
|
||||
p { margin: 14px 0; }
|
||||
a { color: #68a6ff; text-decoration: none; transition: color .15s ease, text-decoration-color .15s ease; }
|
||||
.hidden { color: #dfe9ee; text-decoration: none; }
|
||||
a:hover { text-decoration: underline; }
|
||||
summary { cursor: pointer; }
|
||||
details { background: #1a1c20; border: 1px solid rgba(255,255,255,.06); border-radius: 4px; padding: 14px 16px; margin: 16px 0; }
|
||||
details summary { list-style: none; font-weight: 600; color: #e6eef3; display: flex; align-items: center; }
|
||||
details summary::-webkit-details-marker { display: none; }
|
||||
details summary::before { content: "▸"; margin-right: 8px; transition: transform .15s ease; color: #68a6ff; }
|
||||
details[open] summary::before { transform: rotate(90deg); }
|
||||
summary::after { content: "Expand"; margin-left: auto; font-size: 13px; color: #9aa6b1; }
|
||||
details[open] summary::after { content: "Collapse"; }
|
||||
details > *:not(summary) { margin-top: 12px; }
|
||||
.note, pre, code { background: #1a1c20; border: 1px solid rgba(255,255,255,.06); }
|
||||
.note { padding: 20px; border-radius: 4px; background: #1a1c20; border: 1px solid rgba(255,255,255,.06); margin: 28px 0; color: #dfe9ee; }
|
||||
.note strong { color: #f0f6f8; }
|
||||
.muted { color: #9aa6b1; }
|
||||
.lead { font-size: 15px; margin-top: 8px; }
|
||||
.callout { display: block; margin: 12px 0; }
|
||||
.small { font-size: 13px; color: #9aa6b1; margin-top: 6px; }
|
||||
.highlight { font-weight: 700; color: #cde7ff; }
|
||||
ul, ol { margin: 14px 0; padding-left: 26px; }
|
||||
.tl { display: grid; grid-template-columns: repeat(auto-fill, 200px); gap: 15px; list-style-type: none; padding: 0; margin: 0; justify-content: start; }
|
||||
ul.tl li { padding: 10px; width: fit-content; }
|
||||
li { margin: 6px 0; }
|
||||
code { padding: 3px 7px; border-radius: 3px; font-family: "SF Mono", Monaco, "Cascadia Code", "Roboto Mono", Consolas, "Courier New", monospace; font-size: .9em; color: #cde7ff; }
|
||||
pre { padding: 20px; border-radius: 4px; margin: 14px 0; overflow-x: auto; font-family: "SF Mono", Monaco, "Cascadia Code", "Roboto Mono", Consolas, "Courier New", monospace; font-size: 14px; line-height: 1.6; }
|
||||
pre code { background: none; border: none; padding: 0; font-size: inherit; }
|
||||
blockquote { border-left: 3px solid #68a6ff; padding-left: 18px; margin: 14px 0; color: #dfe9ee; font-style: italic; }
|
||||
hr { border: 0; border-top: 1px solid rgba(255,255,255,.1); margin: 26px 0; }
|
||||
img { max-width: 100%; height: auto; border-radius: 4px; margin: 14px 0; }
|
||||
table { width: 100%; border-collapse: collapse; margin: 14px 0; }
|
||||
th, td { padding: 12px 16px; text-align: left; border-bottom: 1px solid rgba(255,255,255,.06); }
|
||||
th { background: #1a1c20; font-weight: 600; color: #f0f6f8; }
|
||||
tr:hover { background: rgba(255,255,255,.02); }
|
||||
.divider { margin: 26px 0; height: 1px; background: rgba(255,255,255,.1); }
|
||||
.section { margin-top: 36px; }
|
||||
.links { margin: 12px 0; }
|
||||
.links a { display: inline-block; margin: 0 14px 6px 0; }
|
||||
strong, b { font-weight: 600; color: #f0f6f8; }
|
||||
em, i { font-style: italic; }
|
||||
.center { display: flex; justify-content: center; align-items: center; }
|
||||
.banner { width: 100%; box-sizing: border-box; text-align: center; background: #1a1c20; padding: 20px; border: 1px solid rgba(255,255,255,.06); border-bottom-right-radius: 8px; border-bottom-left-radius: 8px; color: #e6eef3; margin: -36px 0 28px 0; box-shadow: 0 0.2em 0.6em rgba(0,0,0,.4); }
|
||||
.nav { margin-left: auto; margin-right: auto; }
|
||||
.nav a { color: #cde7ff; }
|
||||
.footer { background: #1a1c20; padding: 20px 0; border-top: 1px solid rgba(255,255,255,.1); font-size: 14px; color: #d4dde3; display: flex; justify-content: center; align-items: center; gap: 24px; margin-top: 28px !important; margin-bottom: 0; }
|
||||
.left { text-align: left; float: left; }
|
||||
.right { text-align: right; float: right; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
]],
|
||||
footer = footer or [[
|
||||
footer = footer or [[
|
||||
<footer class="footer">
|
||||
<a href="https://git.vxserver.dev/fSD/fes" target="_blank">Fes Powered</a>
|
||||
<a href="https://www.lua.org/" target="_blank">Lua Powered</a>
|
||||
@@ -390,36 +109,39 @@ em, i {
|
||||
</body>
|
||||
</html>
|
||||
]],
|
||||
parts = {}
|
||||
}
|
||||
return setmetatable(self, M)
|
||||
parts = {}
|
||||
}
|
||||
|
||||
return setmetatable(self, M)
|
||||
end
|
||||
|
||||
function M:custom(str)
|
||||
table.insert(self.parts, str)
|
||||
return self
|
||||
table.insert(self.parts, str)
|
||||
return self
|
||||
end
|
||||
|
||||
for name, func in pairs(std) do
|
||||
if type(func) == "function" then
|
||||
M[name] = function(self, ...)
|
||||
local result = func(...)
|
||||
table.insert(self.parts, result)
|
||||
return self
|
||||
end
|
||||
end
|
||||
if type(func) == "function" then
|
||||
M[name] = function(self, ...)
|
||||
local result = func(...)
|
||||
table.insert(self.parts, result)
|
||||
return self
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function M:build()
|
||||
local header = self.header
|
||||
header = header:gsub("{{TITLE}}", self.title or "Document")
|
||||
header = header:gsub("{{FAVICON}}", self.favicon or "")
|
||||
local footer = self.footer:gsub("{{COPYRIGHT}}", self.copyright or "© The Copyright Holder")
|
||||
return header .. table.concat(self.parts, "\n") .. footer
|
||||
local header = self.header
|
||||
local safe_title = self.title or "Document"
|
||||
local safe_favicon = self.favicon:gsub("%%", "%%%%")
|
||||
header = header:gsub("{{TITLE}}", safe_title)
|
||||
header = header:gsub("{{FAVICON}}", safe_favicon)
|
||||
local footer = self.footer:gsub("{{COPYRIGHT}}", self.copyright or "© The Copyright Holder")
|
||||
return header .. table.concat(self.parts, "\n") .. footer
|
||||
end
|
||||
|
||||
M.__tostring = function(self)
|
||||
return self:build()
|
||||
return self:build()
|
||||
end
|
||||
|
||||
return M
|
||||
|
||||
@@ -244,4 +244,10 @@ function M.nav(link, str)
|
||||
return '<a class="nav" href="' .. link .. '">' .. str .. "</a>"
|
||||
end
|
||||
|
||||
function M.rl(r, l)
|
||||
r = r or ""
|
||||
l = l or ""
|
||||
return string.format('<span class="left">%s</span><span class="right">%s</span>', r, l)
|
||||
end
|
||||
|
||||
return M
|
||||
|
||||
@@ -9,6 +9,7 @@ site:note(
|
||||
fes.std.ul({
|
||||
fes.std.a("page1"),
|
||||
fes.std.a("page2"),
|
||||
fes.std.a("sub/subpage"),
|
||||
})
|
||||
)
|
||||
|
||||
|
||||
14
examples/multi-page/www/sub/subpage.lua
Normal file
14
examples/multi-page/www/sub/subpage.lua
Normal file
@@ -0,0 +1,14 @@
|
||||
local fes = require("fes")
|
||||
local site = fes.fes()
|
||||
|
||||
site.title = "Subpage"
|
||||
site.copyright = fes.util.copyright("https://git.vxserver.dev/fSD", "fSD")
|
||||
|
||||
site:h1("Subpage")
|
||||
site:note(
|
||||
fes.std.ul({
|
||||
fes.std.a("/", "Home"),
|
||||
})
|
||||
)
|
||||
|
||||
return site
|
||||
@@ -18,6 +18,43 @@ import (
|
||||
"fes/src/config"
|
||||
)
|
||||
|
||||
func handleDir(entries []os.DirEntry, wwwDir string, routes map[string]string, base string) error {
|
||||
for _, entry := range entries {
|
||||
if entry.IsDir() {
|
||||
sub := filepath.Join(wwwDir, entry.Name())
|
||||
subs, err := os.ReadDir(sub)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read %s: %w", sub, err)
|
||||
}
|
||||
next := base + "/" + entry.Name()
|
||||
if err := handleDir(subs, sub, routes, next); err != nil {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
}
|
||||
if strings.HasSuffix(entry.Name(), ".lua") {
|
||||
name := strings.TrimSuffix(entry.Name(), ".lua")
|
||||
path := filepath.Join(wwwDir, entry.Name())
|
||||
if name == "index" {
|
||||
if base == "" {
|
||||
routes["/"] = path
|
||||
routes["/index"] = path
|
||||
} else {
|
||||
routes[base] = path
|
||||
routes[base+"/index"] = path
|
||||
}
|
||||
} else {
|
||||
if base == "" {
|
||||
routes["/"+name] = path
|
||||
} else {
|
||||
routes[base+"/"+name] = path
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func fixMalformedToml(content string) string {
|
||||
re := regexp.MustCompile(`(?m)^(\s*\w+\s*=\s*)$`)
|
||||
return re.ReplaceAllStringFunc(content, func(match string) string {
|
||||
@@ -209,11 +246,11 @@ func loadLua(luaDir string, entry string, cfg *config.MyConfig) (string, error)
|
||||
}
|
||||
|
||||
func Start(dir string) error {
|
||||
doc, err := os.ReadFile(filepath.Join(dir, "Fes.toml"))
|
||||
tomlDocument, err := os.ReadFile(filepath.Join(dir, "Fes.toml"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
docStr := fixMalformedToml(string(doc))
|
||||
docStr := fixMalformedToml(string(tomlDocument))
|
||||
var cfg config.MyConfig
|
||||
err = toml.Unmarshal([]byte(docStr), &cfg)
|
||||
if err != nil {
|
||||
@@ -227,18 +264,7 @@ func Start(dir string) error {
|
||||
}
|
||||
|
||||
routes := make(map[string]string)
|
||||
for _, entry := range entries {
|
||||
if !entry.IsDir() && strings.HasSuffix(entry.Name(), ".lua") {
|
||||
baseName := strings.TrimSuffix(entry.Name(), ".lua")
|
||||
luaPath := filepath.Join(wwwDir, entry.Name())
|
||||
if baseName == "index" {
|
||||
routes["/"] = luaPath
|
||||
routes["/index"] = luaPath
|
||||
} else {
|
||||
routes["/"+baseName] = luaPath
|
||||
}
|
||||
}
|
||||
}
|
||||
handleDir(entries, wwwDir, routes, "")
|
||||
|
||||
for route, luaPath := range routes {
|
||||
func(rt string, lp string) {
|
||||
|
||||
Reference in New Issue
Block a user