Compare commits
17 Commits
1e15e20175
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fd4922a980 | ||
| ac30aea1fa | |||
| eb5d793802 | |||
| 4889f1afae | |||
| b1ef556eb5 | |||
| 7fc4498dd7 | |||
| 6deaf47565 | |||
| 7f956d8bf0 | |||
| 73b2ad0f11 | |||
| 0994a28e77 | |||
| 1b6d27da99 | |||
| 87a84d6443 | |||
| fedb515df1 | |||
| 383ba0d831 | |||
| af57f1a49d | |||
| 03af8d61c7 | |||
| e36f5bc579 |
6
Makefile
6
Makefile
@@ -8,12 +8,12 @@ deps:
|
||||
$(GO) mod download
|
||||
|
||||
build: deps
|
||||
$(GO) build -ldflags "-X fes/modules/version.gitCommit=$(shell git rev-parse --short HEAD)" -o fes
|
||||
CGO_ENABLED=0 $(GO) build -ldflags "-X fes/modules/version.gitCommit=$(shell git rev-parse --short HEAD)" -o fes
|
||||
@echo "Fes is now built to ./fes"
|
||||
|
||||
lint:
|
||||
$(GO) vet ./...
|
||||
$(GO) fmt ./...
|
||||
|
||||
install:
|
||||
$(GO) install fes
|
||||
install: build
|
||||
@cp fes /usr/local/bin
|
||||
|
||||
41
README.md
41
README.md
@@ -1,11 +1,13 @@
|
||||
# Fes
|
||||
|
||||
A lightweight, static, and opinionated microframework.
|
||||
Fes is an embedded Lua microwebframework for create static, extensible
|
||||
websites. Using file-based routes you can easily structure you website just by
|
||||
moving files around. See [fsdproject.org](https://fsdproject.org) for a
|
||||
real-world example.
|
||||
|
||||
## Usage
|
||||
|
||||
This is the `fes new <project>` output
|
||||
## A Simple Example
|
||||
```lua
|
||||
-- project/www/index.lua as created from fes new project
|
||||
local fes = require("fes")
|
||||
local site = fes.fes()
|
||||
|
||||
@@ -14,32 +16,9 @@ site:h1("Hello, World!")
|
||||
return site
|
||||
```
|
||||
|
||||
This can be ran with `fes run <project>` where `<project>` is the location of the website.
|
||||
|
||||
## Examples
|
||||
|
||||
See `examples/` for different features, `canonical/` contains the best practices for this microframework.
|
||||
|
||||
## Build
|
||||
|
||||
```sh
|
||||
git clone https://git.vxserver.dev/fSD/fes.git
|
||||
cd fes
|
||||
|
||||
go build .
|
||||
./fes run examples/hello-world # if this works install
|
||||
|
||||
go install fes
|
||||
```
|
||||
$ fes run project
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
Run `fes doc` for the documentation website or goto [docs.vxserver.dev](https://docs.vxserver.dev)
|
||||
|
||||
## License
|
||||
|
||||
ISC License
|
||||
|
||||
Copyright (C) 2025-2026 fSD
|
||||
|
||||
See `COPYING`
|
||||
## Contributing
|
||||
See [fSD hacking](https://fsdproject.org/hacking) and [fSD community](https://fsdproject.org/community)
|
||||
|
||||
240
index.html
240
index.html
@@ -276,10 +276,6 @@ return site</code></pre>
|
||||
<td><code>-p <port></code></td>
|
||||
<td>Set the server port.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>-static</code></td>
|
||||
<td>Render and save all pages. (this feature is yet to be implemented)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>-version</code></td>
|
||||
<td>Print the version.</td>
|
||||
@@ -305,7 +301,7 @@ return site</code></pre>
|
||||
<td>Generate a site object</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>:custom()</code></td>
|
||||
<td><code>:g()</code></td>
|
||||
<td>Add a custom string to the site body</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -323,30 +319,6 @@ return site</code></pre>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>std.fes_version()</code></td>
|
||||
<td>Get the current version of fes.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>std.site_version()</code></td>
|
||||
<td>Get the current version of the site, defined in <code>Fes.toml</code>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>std.site_name()</code></td>
|
||||
<td>Get the current name of the site, defined in <code>Fes.toml</code>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>std.site_title()</code></td>
|
||||
<td>Get the current name of the site, defined in <code>Fes.toml</code>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>std.site_authors()</code></td>
|
||||
<td>Get a table of the authors of the site, defined in <code>Fes.toml</code>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>std.join</code></td>
|
||||
<td>Get a table of the authors of the site, defined in <code>Fes.toml</code>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>std.a(link: string, str: string)</code></td>
|
||||
<td>Returns an anchor tag.</td>
|
||||
@@ -448,7 +420,7 @@ return site</code></pre>
|
||||
<td>Returns a div of class <code>class</code> with content of <code>content</code>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>std.spa(content: string, class: string)</code></td>
|
||||
<td><code>std.span(content: string, class: string)</code></td>
|
||||
<td>Returns a span of class <code>class</code> with content of <code>content</code>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -486,15 +458,179 @@ return site</code></pre>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>symbol.copyright</code></td>
|
||||
<td>©</td> </tr>
|
||||
<td><code>symbol.legal.copyright</code></td>
|
||||
<td>©</td> </tr>
|
||||
<tr>
|
||||
<td><code>Registered Trademark</code></td>
|
||||
<td>®</td>
|
||||
<td><code>symbol.legal.registered_trademark</code></td>
|
||||
<td>®</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Trademark</code></td>
|
||||
<td>™</td>
|
||||
<td><code>symbol.legal.trademark</code></td>
|
||||
<td>™</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>symbol.currency.euro</code></td>
|
||||
<td>€</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>symbol.currency.pound</code></td>
|
||||
<td>£</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>symbol.currency.yen</code></td>
|
||||
<td>¥</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>symbol.currency.cent</code></td>
|
||||
<td>¢</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>symbol.currency.dollar</code></td>
|
||||
<td>$</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>symbol.currency.plus_minus</code></td>
|
||||
<td>±</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>symbol.currency.multiply</code></td>
|
||||
<td>×</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>symbol.currency.divide</code></td>
|
||||
<td>÷</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>symbol.currency.not_equal</code></td>
|
||||
<td>≠</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>symbol.currency.less_equal</code></td>
|
||||
<td>≤</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>symbol.currency.greater_equal</code></td>
|
||||
<td>≥</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>symbol.currency.infinity</code></td>
|
||||
<td>∞</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>symbol.currency.approx</code></td>
|
||||
<td>≈</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>symbol.arrows.left</code></td>
|
||||
<td>←</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>symbol.arrows.right</code></td>
|
||||
<td>→</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>symbol.arrows.up</code></td>
|
||||
<td>↑</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>symbol.arrows.down</code></td>
|
||||
<td>↓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>symbol.arrows.left_right</code></td>
|
||||
<td>↔</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>symbol.punctuation.left_double_quote</code></td>
|
||||
<td>“</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>symbol.punctuation.right_double_quote</code></td>
|
||||
<td>”</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>symbol.punctuation.left_single_quote</code></td>
|
||||
<td>‘</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>symbol.punctuation.right_single_quote</code></td>
|
||||
<td>’</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>symbol.punctuation.ellipsis</code></td>
|
||||
<td>…</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>symbol.punctuation.em_dash</code></td>
|
||||
<td>—</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>symbol.punctuation.en_dash</code></td>
|
||||
<td>–</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>symbol.whitespace.non_breaking</code></td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>symbol.whitespace.thin</code></td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>symbol.symbols.degree</code></td>
|
||||
<td>°</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>symbol.symbols.micro</code></td>
|
||||
<td>µ</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>symbol.symbols.section</code></td>
|
||||
<td>§</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>symbol.symbols.paragraph</code></td>
|
||||
<td>¶</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>symbol.symbols.check</code></td>
|
||||
<td>✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>symbol.symbols.cross</code></td>
|
||||
<td>✗</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>symbol.symbols.bullet</code></td>
|
||||
<td>•</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>symbol.symbols.middle_dot</code></td>
|
||||
<td>·</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>symbol.symbols.broken_bar</code></td>
|
||||
<td>¦</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>symbol.html.less_than</code></td>
|
||||
<td><</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>symbol.html.greater_than</code></td>
|
||||
<td>></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>symbol.html.ampersand</code></td>
|
||||
<td>&</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>symbol.html.double_quote</code></td>
|
||||
<td>"</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>symbol.html.single_quote</code></td>
|
||||
<td>'</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -514,6 +650,14 @@ return site</code></pre>
|
||||
<td><code>util.copyright(link: string, holder: string)</code></td>
|
||||
<td>Used when setting the website copyright holder.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>util.ls(dir)</code></td>
|
||||
<td>Returns a table of the files in the given directory</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>util.run(cmd)</code></td>
|
||||
<td>Returns the output of the provided command. stdout only.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>Dkjson</h3>
|
||||
@@ -553,28 +697,6 @@ return site</code></pre>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>Site</h3>
|
||||
<table> <thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>site.version</code></td>
|
||||
<td>The version of the website found in the Fes.toml</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>site.name</code></td>
|
||||
<td>The name of the website found in the Fes.toml</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>site.authors</code></td>
|
||||
<td>A table of all authors defined in Fes.toml</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>App</h3>
|
||||
Fes's <code>app</code> module is a special table
|
||||
because it contains user defined functions. These
|
||||
@@ -627,7 +749,7 @@ return hello</pre></code> This can be called from another with,
|
||||
</section>
|
||||
|
||||
<footer>
|
||||
<p>Last updated: 2025-12-27</p>
|
||||
<p>Last updated: 2026-01-22</p>
|
||||
</footer>
|
||||
</main>
|
||||
</body>
|
||||
|
||||
19
lib/util.lua
19
lib/util.lua
@@ -7,18 +7,10 @@ function M.cc(tbl, sep)
|
||||
return table.concat(tbl, sep or "")
|
||||
end
|
||||
|
||||
function M.year(y)
|
||||
return y or os.date("%Y")
|
||||
end
|
||||
|
||||
function M.copyright(link, holder)
|
||||
return symbol.legal.copyright .. " " .. std.external(link, holder)
|
||||
end
|
||||
|
||||
function M.license(name)
|
||||
return symbol.legal.registered .. " " .. name
|
||||
end
|
||||
|
||||
function M.ls(dir)
|
||||
local p = io.popen('ls -A -1 -- ' .. string.format('%q', dir))
|
||||
if not p then
|
||||
@@ -32,4 +24,15 @@ function M.ls(dir)
|
||||
return t
|
||||
end
|
||||
|
||||
function M.run(cmd)
|
||||
cmd = cmd or "echo nil"
|
||||
local p = io.popen(cmd)
|
||||
if not p then
|
||||
return nil
|
||||
end
|
||||
local r = p:read("*a"):gsub("%s+$", "")
|
||||
p:close()
|
||||
return r
|
||||
end
|
||||
|
||||
return M
|
||||
|
||||
@@ -118,7 +118,7 @@ Check out [Fes's docs](https://docs.vxserver.dev/static/fes.html).`, "$$", "`"),
|
||||
|
||||
ui.Hint("you can run this with `fes run %s`", dir)
|
||||
|
||||
fmt.Println("Created new Fes project at", func () string {
|
||||
fmt.Println("Created new Fes project at", func() string {
|
||||
if cwd, err := os.Getwd(); err != nil {
|
||||
return dir
|
||||
} else {
|
||||
|
||||
@@ -18,7 +18,17 @@ func Start(dir string) {
|
||||
ui.Error(fmt.Sprintf("failed to change directory to %s", dir), err)
|
||||
}
|
||||
|
||||
ui.Log("running root=%s, port=%d.", filepath.Clean(dir), *config.Port)
|
||||
root := filepath.Clean(dir)
|
||||
|
||||
if root == "." {
|
||||
if res, err := filepath.Abs(root); err == nil {
|
||||
root = filepath.Base(res)
|
||||
} else {
|
||||
ui.Error("failed to get absolute path", err)
|
||||
}
|
||||
}
|
||||
|
||||
ui.Log("running root=%s, port=%d.", root, *config.Port)
|
||||
|
||||
routes := loadDirs()
|
||||
|
||||
@@ -40,7 +50,13 @@ func Start(dir string) {
|
||||
err = readArchive(w, route)
|
||||
} else {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
w.Write([]byte("not found :("))
|
||||
w.Write([]byte(`<html>
|
||||
<head><title>404 Not Found</title></head>
|
||||
<body>
|
||||
<center><h1>404 Not Found</h1></center>
|
||||
<hr><center>fes</center>
|
||||
</body>
|
||||
</html>`))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ var gitCommit string = "devel"
|
||||
|
||||
const PROGRAM_NAME string = "fes"
|
||||
const PROGRAM_NAME_LONG string = "fes/fSD"
|
||||
const VERSION string = "1.0.1"
|
||||
const VERSION string = "1.2.0"
|
||||
|
||||
func Version() {
|
||||
fmt.Printf("%s version %s\n", PROGRAM_NAME_LONG, VERSION)
|
||||
|
||||
Reference in New Issue
Block a user