Compare commits

...

17 Commits

Author SHA1 Message Date
vx-clutch
fd4922a980 chore: update todo 2026-03-19 23:58:03 -04:00
ac30aea1fa fix typo 2026-02-01 10:16:19 -05:00
eb5d793802 update util 2026-02-01 09:59:33 -05:00
4889f1afae build static binary 2026-02-01 09:52:59 -05:00
b1ef556eb5 add command runner util 2026-01-31 16:56:18 -05:00
7fc4498dd7 makefile copies instead of moves 2026-01-28 10:21:27 -05:00
6deaf47565 fix install overwrote local bin 2026-01-28 10:19:57 -05:00
7f956d8bf0 update install to move ./fes instead of using go install
install rebuilds and makes the -V1 output devel
2026-01-28 10:18:17 -05:00
73b2ad0f11 fix root for the '.' case 2026-01-26 18:19:05 -05:00
0994a28e77 update documentation 2026-01-22 21:52:15 -05:00
1b6d27da99 Update README.md 2026-01-20 13:01:37 -05:00
87a84d6443 Update README.md 2026-01-20 13:01:13 -05:00
fedb515df1 rewrite README 2026-01-20 13:00:55 -05:00
383ba0d831 Merge branch 'rewrite' 2026-01-20 12:48:41 -05:00
af57f1a49d change the not found content 2026-01-20 12:47:58 -05:00
03af8d61c7 format 2026-01-20 12:47:44 -05:00
e36f5bc579 Merge pull request 'rewrite' (#1) from rewrite into main
Reviewed-on: #1
2026-01-19 16:17:56 -05:00
8 changed files with 226 additions and 105 deletions

View File

@@ -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

View File

@@ -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)

View File

@@ -276,10 +276,6 @@ return site</code></pre>
<td><code>-p &lt;port&gt;</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>&#169;</td> </tr>
<td><code>symbol.legal.copyright</code></td>
<td>&copy;</td> </tr>
<tr>
<td><code>Registered Trademark</code></td>
<td>&#174;</td>
<td><code>symbol.legal.registered_trademark</code></td>
<td>&reg;</td>
</tr>
<tr>
<td><code>Trademark</code></td>
<td>&#8482;</td>
<td><code>symbol.legal.trademark</code></td>
<td>&trade;</td>
</tr>
<tr>
<td><code>symbol.currency.euro</code></td>
<td>&euro;</td>
</tr>
<tr>
<td><code>symbol.currency.pound</code></td>
<td>&pound;</td>
</tr>
<tr>
<td><code>symbol.currency.yen</code></td>
<td>&yen;</td>
</tr>
<tr>
<td><code>symbol.currency.cent</code></td>
<td>&cent;</td>
</tr>
<tr>
<td><code>symbol.currency.dollar</code></td>
<td>$</td>
</tr>
<tr>
<td><code>symbol.currency.plus_minus</code></td>
<td>&plusmn;</td>
</tr>
<tr>
<td><code>symbol.currency.multiply</code></td>
<td>&times;</td>
</tr>
<tr>
<td><code>symbol.currency.divide</code></td>
<td>&divide;</td>
</tr>
<tr>
<td><code>symbol.currency.not_equal</code></td>
<td>&ne;</td>
</tr>
<tr>
<td><code>symbol.currency.less_equal</code></td>
<td>&le;</td>
</tr>
<tr>
<td><code>symbol.currency.greater_equal</code></td>
<td>&ge;</td>
</tr>
<tr>
<td><code>symbol.currency.infinity</code></td>
<td>&infin;</td>
</tr>
<tr>
<td><code>symbol.currency.approx</code></td>
<td>&asymp;</td>
</tr>
<tr>
<td><code>symbol.arrows.left</code></td>
<td>&larr;</td>
</tr>
<tr>
<td><code>symbol.arrows.right</code></td>
<td>&rarr;</td>
</tr>
<tr>
<td><code>symbol.arrows.up</code></td>
<td>&uarr;</td>
</tr>
<tr>
<td><code>symbol.arrows.down</code></td>
<td>&darr;</td>
</tr>
<tr>
<td><code>symbol.arrows.left_right</code></td>
<td>&harr;</td>
</tr>
<tr>
<td><code>symbol.punctuation.left_double_quote</code></td>
<td>&ldquo;</td>
</tr>
<tr>
<td><code>symbol.punctuation.right_double_quote</code></td>
<td>&rdquo;</td>
</tr>
<tr>
<td><code>symbol.punctuation.left_single_quote</code></td>
<td>&lsquo;</td>
</tr>
<tr>
<td><code>symbol.punctuation.right_single_quote</code></td>
<td>&rsquo;</td>
</tr>
<tr>
<td><code>symbol.punctuation.ellipsis</code></td>
<td>&hellip;</td>
</tr>
<tr>
<td><code>symbol.punctuation.em_dash</code></td>
<td>&mdash;</td>
</tr>
<tr>
<td><code>symbol.punctuation.en_dash</code></td>
<td>&ndash;</td>
</tr>
<tr>
<td><code>symbol.whitespace.non_breaking</code></td>
<td>&nbsp;</td>
</tr>
<tr>
<td><code>symbol.whitespace.thin</code></td>
<td>&thinsp;</td>
</tr>
<tr>
<td><code>symbol.symbols.degree</code></td>
<td>&deg;</td>
</tr>
<tr>
<td><code>symbol.symbols.micro</code></td>
<td>&micro;</td>
</tr>
<tr>
<td><code>symbol.symbols.section</code></td>
<td>&sect;</td>
</tr>
<tr>
<td><code>symbol.symbols.paragraph</code></td>
<td>&para;</td>
</tr>
<tr>
<td><code>symbol.symbols.check</code></td>
<td>&check;</td>
</tr>
<tr>
<td><code>symbol.symbols.cross</code></td>
<td>&cross;</td>
</tr>
<tr>
<td><code>symbol.symbols.bullet</code></td>
<td>&bull;</td>
</tr>
<tr>
<td><code>symbol.symbols.middle_dot</code></td>
<td>&middot;</td>
</tr>
<tr>
<td><code>symbol.symbols.broken_bar</code></td>
<td>&brvbar;</td>
</tr>
<tr>
<td><code>symbol.html.less_than</code></td>
<td>&lt;</td>
</tr>
<tr>
<td><code>symbol.html.greater_than</code></td>
<td>&gt;</td>
</tr>
<tr>
<td><code>symbol.html.ampersand</code></td>
<td>&amp;</td>
</tr>
<tr>
<td><code>symbol.html.double_quote</code></td>
<td>&quot;</td>
</tr>
<tr>
<td><code>symbol.html.single_quote</code></td>
<td>&apos;</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>

View File

@@ -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

View File

@@ -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 {

View File

@@ -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
}

View File

@@ -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)

1
todo Normal file
View File

@@ -0,0 +1 @@
footer: update link to direct to a local page for ISC