fes

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 1427d0d7804ac9d2b3525405a5ae1f884755da7e
parent 3cfc9b4aed10ae5365b0856102bf94fe5049d10a
Author: vx-clutch <[email protected]>
Date:   Sun, 14 Dec 2025 19:40:55 -0500

doc: first

Diffstat:
Mcore/std.lua | 40----------------------------------------
Aindex.html | 500+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mmain.go | 4++++
Msrc/config/config.go | 1+
Msrc/doc/doc.go | 7++-----
5 files changed, 507 insertions(+), 45 deletions(-)

diff --git a/core/std.lua b/core/std.lua @@ -186,46 +186,6 @@ function M.site_authors() return {} end --- Join array with separator -function M.join(arr, sep) - arr = arr or {} - sep = sep or ", " - local result = {} - for _, v in ipairs(arr) do - table.insert(result, tostring(v)) - end - return table.concat(result, sep) -end - --- Trim whitespace -function M.trim(str) - str = tostring(str or "") - return str:match("^%s*(.-)%s*$") -end - --- Table HTML generator -function M.table(headers, rows) - headers = headers or {} - rows = rows or {} - - local html = "<table><thead><tr>" - for _, header in ipairs(headers) do - html = html .. "<th>" .. tostring(header) .. "</th>" - end - html = html .. "</tr></thead><tbody>" - - for _, row in ipairs(rows) do - html = html .. "<tr>" - for _, cell in ipairs(row) do - html = html .. "<td>" .. tostring(cell) .. "</td>" - end - html = html .. "</tr>" - end - - html = html .. "</tbody></table>" - return html -end - function M.highlight(str) return '<span class="highlight">' .. (str or "") .. "</span>" end diff --git a/index.html b/index.html @@ -0,0 +1,500 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <title>Documentation 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; +} + +main { + max-width: 830px; + margin: 0 auto; + padding: 36px; +} + +header { + margin-bottom: 36px; +} + +h1 { + font-size: 40px; + font-weight: 700; + margin: 0 0 20px 0; +} + +h2 { + font-size: 32px; + margin: 26px 0 14px; + border-bottom: 1px solid rgba(255,255,255,.1); + padding-bottom: 6px; +} + +h3 { + font-size: 26px; + margin: 22px 0 12px; +} + +p { + margin: 14px 0; +} + +header p { + color: #9aa6b1; +} + +nav { + margin: 28px 0; + padding: 20px; + background: #1a1c20; + border: 1px solid rgba(255,255,255,.06); + border-radius: 4px; +} + +nav h2 { + font-size: 20px; + margin: 0 0 12px 0; + border: none; + padding: 0; +} + +nav ul { + list-style: none; + padding: 0; + margin: 0; +} + +nav li { + margin: 6px 0; +} + +a { + color: #68a6ff; + text-decoration: none; + transition: color .15s ease; +} + +a:hover { + text-decoration: underline; +} + +section { + margin-top: 36px; +} + +ul, ol { + margin: 14px 0; + padding-left: 26px; +} + +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; + background: #1a1c20; + border: 1px solid rgba(255,255,255,.06); +} + +pre { + padding: 20px; + border-radius: 4px; + margin: 14px 0; + overflow-x: auto; + background: #1a1c20; + border: 1px solid rgba(255,255,255,.06); + 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; + color: inherit; +} + +blockquote { + border-left: 3px solid #68a6ff; + padding-left: 18px; + margin: 14px 0; + color: #dfe9ee; + font-style: italic; +} + +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); +} + +footer { + margin-top: 48px; + padding-top: 20px; + border-top: 1px solid rgba(255,255,255,.1); + color: #9aa6b1; + font-size: 14px; +} + </style> +</head> +<body> + <main> + <header> + <h1>Documentation</h1> + <p>Fes: A lightweight, static, and opinionated microframework.</p> + </header> + + <nav> + <h2>Contents</h2> + <ul> + <li><a href="#introduction">Introduction</a></li> + <li><a href="#installation">Installation</a></li> + <li><a href="#usage">Usage</a></li> + <li><a href="#cli-reference">Cli Reference</a></li> + <li><a href="#reference">Reference</a></li> + </ul> + </nav> + + <section id="introduction"> + <h2>Introduction</h2> + <p>Fes, or Free Easy Site, is a microframework used for small static sites. It is not designed for complex web applications and that is why it is good. Yes, I hate modern web and that is the reason this exists.</p> + </section> + + <section id="installation"> + <h2>Installation</h2> + <pre><code>git clone https://git.vxserver.dev/fSD/fes</code></pre> + <pre><code>cd fes</code></pre> + <pre><code>go install fes</code></pre> + </section> + + <section id="usage"> + <h2>Usage</h2> + <p>Typical workflows and examples.</p> + <ul> + <li>Creating project</li> + <li>Hosting websites</li> + <li>Generating websites</li> + </ul> + </section> + + <section id="cli-reference"> + <h2>Cli Reference</h2> + <table> <thead> + <tr> + <th>Name</th> + <th>Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>--help</code></td> + <td>Display help information</td> + </tr> + <tr> + <td><code>--no-color</code></td> + <td>Disable color output</td> + </tr> + <tr> + <td><code>-p &lt;port&gt;</code></td> + <td>Set the server port</td> + </tr> + <tr> + <td><code>new &lt;project&gt;</code></td> + <td>Create a new projet called &lt;project&gt;</td> + </tr> + <tr> + <td><code>doc</code></td> + <td>Open this documention page</td> + </tr> + <tr> + <td><code>run &lt;project&gt;</code></td> + <td>Run the projet called &lt;project&gt;</td> + </tr> + </tbody> + </table> + </section> + + <section id="reference"> + <h2>Reference</h2> + All <code>std</code> functions have binding for the site and can be used like so: <code>site:h1("Hello, World!")</code>, where site is the site object. + <h3>Builtin</h3> + <table> + <thead> + <tr> + <th>Name</th> + <th>Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>fes()</code></td> + <td>Generate a site object</td> + </tr> + <tr> + <td><code>:custom()</code></td> + <td>Add a custom string to the site body</td> + </tr> + </tbody> + </table> + <h3>Std</h3> + <table> + <thead> + <tr> + <th>Name</th> + <th>Description</th> + </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> + </tr> + <tr> + <td><code>std.ha(link: string, str: string)</code></td> + <td>Returns an anchor tag with sytiling to make it hidden.</td> + </tr> + <tr> + <td><code>std.external(link: string, str: string)</code></td> + <td>Returns an anchor tag that opens up in a new tab.</td> + </tr> + <tr> + <td><code>std.note(str: string)</code></td> + <td>Returns a note object.</td> + </tr> + <tr> + <td><code>std.muted(str: string)</code></td> + <td>Returns a muted object.</td> + </tr> + <tr> + <td><code>std.callout(str: string)</code></td> + <td>Returns a callout object.</td> + </tr> + <tr> + <td><code>std.h1(str: string)</code></td> + <td>Returns a header level 1 object.</td> + </tr> + <tr> + <td><code>std.h2(str: string)</code></td> + <td>Returns a header level 2 object.</td> + </tr> + <tr> + <td><code>std.h3(str: string)</code></td> + <td>Returns a header level 3 object.</td> + </tr> + <tr> + <td><code>std.h4(str: string)</code></td> + <td>Returns a header level 4 object.</td> + </tr> + <tr> + <td><code>std.h5(str: string)</code></td> + <td>Returns a header level 5 object.</td> + </tr> + <tr> + <td><code>std.h6(str: string)</code></td> + <td>Returns a header level 6 object.</td> + </tr> + <tr> + <td><code>std.p(str: string)</code></td> + <td>Returns a paragraph object.</td> + </tr> + <tr> + <td><code>std.pre(str: string)</code></td> + <td>Returns preformated text.</td> + </tr> + <tr> + <td><code>std.code(str: string)</code></td> + <td>Returns a codeblock.</td> + </tr> + <tr> + <td><code>std.ul(items: {...strings})</code></td> + <td>Generates an unordered list from a table of strings.</td> + </tr> + <tr> + <td><code>std.ol(items: {...strings})</code></td> + <td>Generates an ordered list from a table of strings.</td> + </tr> + <tr> + <td><code>std.tl(items: {...strings})</code></td> + <td>Generates a table from a table of strings.</td> + </tr> + <tr> + <td><code>std.blockquote(str: string)</code></td> + <td>Returns a blockquote.</td> + </tr> + <tr> + <td><code>std.hr()</code></td> + <td>Returns a horizonal rule.</td> + </tr> + <tr> + <td><code>std.img(src: string, alt: string)</code></td> + <td>Returns an image at location source with given alternative text.</td> + </tr> + <tr> + <td><code>std.strong(str: string)</code></td> + <td>Returns bolded text.</td> + </tr> + <tr> + <td><code>std.em(str: string)</code></td> + <td>Returns italicized text.</td> + </tr> + <tr> + <td><code>std.br()</code></td> + <td>Returns a break.</td> + </tr> + <tr> + <td><code>std.div(content: string, class: string)</code></td> + <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>Returns a span of class <code>class</code> with content of <code>content</code>.</td> + </tr> + <tr> + <td><code>std.escape(str: string)</code></td> + <td>Returns an html escaped string.</td> + </tr> + <tr> + <td><code>std.highlight(str: string)</code></td> + <td>Returns highlighted text.</td> + </tr> + <tr> + <td><code>std.banner(str: string)</code></td> + <td>Returns a banner that is attached to the top of the site.</td> + </tr> + <tr> + <td><code>std.center(str: string)</code></td> + <td>Returns centered text.</td> + </tr> + <tr> + <td><code>std.nav(link: string, str: string)</code></td> + <td>Returns a speical navigation link, used for in-site traversal.</td> + </tr> + <tr> + <td><code>std.rl(r: string, l: string)</code></td> + <td>Right and light alight content.</td> + </tr> + </tbody> + </table> + <h3>Symbol</h3> + <table> <thead> + <tr> + <th>Name</th> + <th>Symbol</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>symbol.copyright</code></td> + <td>&#169;</td> </tr> + <tr> + <td><code>Registered Trademark</code></td> + <td>&#174;</td> + </tr> + <tr> + <td><code>Trademark</code></td> + <td>&#8482;</td> + </tr> + </tbody> + </table> + <h3>Util</h3> + <table> <thead> + <tr> + <th>Name</th> + <th>Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>util.cc(tbl: {...strings})</code></td> + <td>Concatenate a table of strings into a single string.</td> + </tr> + <tr> + <td><code>util.copyright(link: string, holder: string)</code></td> + <td>Used when setting the website copyright holder.</td> + </tr> + </tbody> + </table> + <h3>Dkjson</h3> + This is a third party object and is best documented <a href="https://dkolf.de/dkjson-lua/documentation" target="_blank">here</a> + <table> <thead> + <tr> + <th>Name</th> + <th>Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>dkjson.encode(obj: {...any})</code></td> + <td>Serilize a Lua table into JSON.</td> + </tr> + <tr> + <td><code>dkjson.decode(obj: {...any})</code></td> + <td>Deserilize JSON into a Lua table.</td> + </tr> + </tbody> + </table> + </section> + + <footer> + <p>Last updated: 2025-12-14</p> + </footer> + </main> +</body> +</html> diff --git a/main.go b/main.go @@ -18,10 +18,14 @@ import ( //go:embed core/* var core embed.FS +//go:embed index.html +var documentation string + func init() { config.Port = flag.Int("p", 3000, "Set the server port") config.Color = flag.Bool("no-color", false, "Disable color output") config.Core = core + config.Doc = documentation } func main() { diff --git a/src/config/config.go b/src/config/config.go @@ -6,6 +6,7 @@ import ( ) var Core embed.FS +var Doc string var Port *int var Color *bool diff --git a/src/doc/doc.go b/src/doc/doc.go @@ -1,6 +1,7 @@ package doc import ( + "fes/src/config" "fmt" "os" "path/filepath" @@ -12,12 +13,8 @@ func Open() error { fmt.Println("Opening documentation in browser") tmpFile := filepath.Join(os.TempDir(), "doc.html") - content := `<html><body><pre> -This feature is not implemented yet. It will be once the doc site -is up and running, for now read through the core/ files and examples. -</pre></body></html>` - if err := os.WriteFile(tmpFile, []byte(content), 0644); err != nil { + if err := os.WriteFile(tmpFile, []byte(config.Doc), 0644); err != nil { return err }