diff --git a/Makefile b/Makefile
index 7fb5e01..ddd12b6 100644
--- a/Makefile
+++ b/Makefile
@@ -232,6 +232,18 @@ event_debug:
${MAKE} -C kc3s debug
${MAKE} -C event debug
+fx: httpd
+ httpd/.libs/kc3_httpd -C httpd/fx -d
+
+fx_asan: httpd_asan
+ httpd/.libs/kc3_httpd_asan -C httpd/fx -d
+
+fx_cov: httpd_cov
+ httpd/.libs/kc3_httpd_cov -C httpd/fx -d
+
+fx_debug: httpd_debug
+ httpd/.libs/kc3_httpd_debug -C httpd/fx -d
+
gcovr:
${MAKE} -C libkc3 gcovr
${MAKE} -C ikc3 gcovr
@@ -255,6 +267,12 @@ gdb_demo_gl:
${MAKE} debug
${MAKE} -C libkc3 gdb_demo_gl
+gdb_fx: httpd_debug
+ ${MAKE} -C httpd gdb_fx
+
+gdb_fx_asan: httpd_asan
+ ${MAKE} -C httpd gdb_fx_asan
+
gdb_ikc3:
${MAKE} -C libtommath debug
${MAKE} -C ucd2c
@@ -411,6 +429,20 @@ httpd:
${MAKE} -C http build
${MAKE} -C httpd build
+httpd_debug:
+ ${MAKE} -C libtommath debug
+ ${MAKE} -C ucd2c
+ ${MAKE} -C libkc3 debug
+ ${MAKE} -C ikc3 debug
+ ${MAKE} -C kc3s debug
+ ${MAKE} -C ekc3 debug
+ ${MAKE} -C event debug
+ ${MAKE} -C json debug
+ ${MAKE} -C markdown debug
+ ${MAKE} -C socket debug
+ ${MAKE} -C http debug
+ ${MAKE} -C httpd debug
+
ikc3:
${MAKE} -C libtommath build
${MAKE} -C ucd2c
@@ -1011,7 +1043,13 @@ test_socket_debug:
event_asan \
event_cov \
event_debug \
+ fx \
+ fx_asan \
+ fx_cov \
+ fx_debug \
gcovr \
+ gdb_fx \
+ gdb_fx_asan \
gdb_test \
gdb_test_asan \
gdb_test_debug \
diff --git a/httpd/Makefile b/httpd/Makefile
index ff04799..1ebf9cd 100644
--- a/httpd/Makefile
+++ b/httpd/Makefile
@@ -40,9 +40,27 @@ debug: kc3_httpd_debug
distclean:
rm -rf ${DISTCLEANFILES}
+fx: kc3_httpd
+ httpd/.libs/kc3_httpd -C httpd/fx -d
+
+fx_asan: kc3_httpd_asan
+ httpd/.libs/kc3_httpd_asan -C httpd/fx -d
+
+fx_cov: kc3_httpd_cov
+ httpd/.libs/kc3_httpd_cov -C httpd/fx -d
+
+fx_debug: kc3_httpd_debug
+ httpd/.libs/kc3_httpd_debug -C httpd/fx -d
+
gcovr:
gcovr --gcov-executable ${GCOV} --html-details kc3_httpd.html
+gdb_fx: kc3_httpd_debug
+ cd fx && gdb ../.libs/kc3_httpd_debug
+
+gdb_fx_asan: kc3_httpd_asan
+ cd fx && gdb ../.libs/kc3_httpd_asan
+
gdb_httpd: debug
if [ -f kc3_httpd_debug.core ]; then gdb .libs/kc3_httpd_debug kc3_httpd_debug.core; else gdb .libs/kc3_httpd_debug; fi
diff --git a/httpd/fx/app/controllers/fx_controller.kc3 b/httpd/fx/app/controllers/fx_controller.kc3
new file mode 100644
index 0000000..214cc6f
--- /dev/null
+++ b/httpd/fx/app/controllers/fx_controller.kc3
@@ -0,0 +1,9 @@
+defmodule FXController do
+
+ def route = fn (req) do
+ if (req.method == GET || req.method == HEAD) do
+ path = "." + req.url,
+ end
+ end
+
+end
diff --git a/httpd/fx/app/templates/fx/menu.html.ekc3 b/httpd/fx/app/templates/fx/menu.html.ekc3
new file mode 100644
index 0000000..9e069bb
--- /dev/null
+++ b/httpd/fx/app/templates/fx/menu.html.ekc3
@@ -0,0 +1,13 @@
+<ul>
+ <%= raw List.join(List.map(index, fn (file) {
+ """
+ <li>
+ <a href="#{URL.escape(file.url)}">#{HTML.escape(file.name)}</a>
+ #{if (file.type == :dir) do
+ FXView.render_menu(file.items)
+ else
+ ""
+ end}
+ </li>
+"""}), "\n") %>
+</ul>
diff --git a/httpd/fx/app/templates/fx/show.html.ekc3 b/httpd/fx/app/templates/fx/show.html.ekc3
new file mode 100644
index 0000000..cca060e
--- /dev/null
+++ b/httpd/fx/app/templates/fx/show.html.ekc3
@@ -0,0 +1,8 @@
+<div class="row">
+ <div class="bg-gray col-12 col-sm-4 col-lg-3 left-col">
+ <%= raw menu %>
+ </div>
+ <div class="col-12 col-sm-8 col-lg-9">
+ <h1><%= title %></h1>
+ </div>
+</div>
diff --git a/httpd/fx/app/templates/layout.html.ekc3 b/httpd/fx/app/templates/layout.html.ekc3
new file mode 100644
index 0000000..2ce18c6
--- /dev/null
+++ b/httpd/fx/app/templates/layout.html.ekc3
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8"/>
+ <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
+ <title><%= title %></title>
+ <link rel="stylesheet" href="/_assets/app.css"/>
+ <script defer type="text/javascript" src="/_assets/app.js"></script>
+ <link rel="icon" type="image/png" sizes="128x128" href="/_images/kc3.128.png">
+ <link rel="icon" type="image/png" sizes="64x64" href="/_images/kc3.64.png">
+ <link rel="icon" type="image/png" sizes="32x32" href="/_images/kc3.32.png">
+ <link rel="icon" type="image/png" sizes="16x16" href="/_images/kc3.16.png">
+ </head>
+ <body>
+ <%= raw nav %>
+ <%= raw page %>
+ </body>
+</html>
diff --git a/httpd/fx/app/templates/nav.html.ekc3 b/httpd/fx/app/templates/nav.html.ekc3
new file mode 100644
index 0000000..e02a5f1
--- /dev/null
+++ b/httpd/fx/app/templates/nav.html.ekc3
@@ -0,0 +1,22 @@
+<nav class="navbar navbar-expand-sm navbar-dark bg-dark">
+ <div class="container">
+ <a class="navbar-brand" href="/">
+ <div class="doc-logo">
+ <span><b>⬢</b></span> kc3-lang
+ </div>
+ </a>
+ <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
+ <span class="navbar-toggler-icon"></span>
+ </button>
+ <div class="collapse navbar-collapse" id="navbarSupportedContent">
+ <ul class="navbar-nav me-auto mb-2 mb-lg-0">
+ <li class="nav-item">
+ <a class="navbar-link" href="/release/v0.1.13/">v0.1.13</a>
+ </li>
+ <li class="nav-item">
+ <a class="navbar-link" href="/doc/">Documentation</a>
+ </li>
+ </ul>
+ </div>
+ </div>
+</nav>
diff --git a/httpd/fx/app/views/fx_view.kc3 b/httpd/fx/app/views/fx_view.kc3
new file mode 100644
index 0000000..41614d7
--- /dev/null
+++ b/httpd/fx/app/views/fx_view.kc3
@@ -0,0 +1,20 @@
+defmodule FXView do
+
+ def menu_template =
+ EKC3.load("app/templates/fx/menu.html.ekc3")
+
+ def show_template =
+ EKC3.load("app/templates/fx/show.html.ekc3")
+
+ def properties_template =
+ EKC3.load("app/templates/fx/properties.html.ekc3")
+
+ def render_menu = fn (index) {
+ EKC3.render(menu_template)
+ }
+
+ def render_show = fn (menu, html) {
+ EKC3.render(show_template)
+ }
+
+end
diff --git a/httpd/fx/app/views/layout_view.kc3 b/httpd/fx/app/views/layout_view.kc3
new file mode 100644
index 0000000..672aada
--- /dev/null
+++ b/httpd/fx/app/views/layout_view.kc3
@@ -0,0 +1,13 @@
+defmodule LayoutView do
+
+ def template = EKC3.load("app/templates/layout.html.ekc3")
+
+ def template_nav = EKC3.load("app/templates/nav.html.ekc3")
+
+ def nav = EKC3.render(template_nav)
+
+ def render = fn (title, page) {
+ EKC3.render(template)
+ }
+
+end
diff --git a/httpd/fx/config/mime.types b/httpd/fx/config/mime.types
new file mode 100644
index 0000000..c6cc75a
--- /dev/null
+++ b/httpd/fx/config/mime.types
@@ -0,0 +1,102 @@
+
+types {
+ text/html html htm shtml;
+ text/css css;
+ text/xml xml;
+ image/gif gif;
+ image/jpeg jpeg jpg;
+ application/javascript js;
+ application/atom+xml atom;
+ application/rss+xml rss;
+
+ text/mathml mml;
+ text/plain txt;
+ text/vnd.sun.j2me.app-descriptor jad;
+ text/vnd.wap.wml wml;
+ text/x-component htc;
+
+ image/avif avif;
+ image/png png;
+ image/svg+xml svg svgz;
+ image/tiff tif tiff;
+ image/vnd.wap.wbmp wbmp;
+ image/webp webp;
+ image/x-icon ico;
+ image/x-jng jng;
+ image/x-ms-bmp bmp;
+
+ font/woff woff;
+ font/woff2 woff2;
+
+ application/java-archive jar war ear;
+ application/json json;
+ application/mac-binhex40 hqx;
+ application/msword doc;
+ application/pdf pdf;
+ application/postscript ps eps ai;
+ application/rtf rtf;
+ application/vnd.apple.mpegurl m3u8;
+ application/vnd.google-earth.kml+xml kml;
+ application/vnd.google-earth.kmz kmz;
+ application/vnd.ms-excel xls;
+ application/vnd.ms-fontobject eot;
+ application/vnd.ms-powerpoint ppt;
+ application/vnd.oasis.opendocument.graphics odg;
+ application/vnd.oasis.opendocument.presentation odp;
+ application/vnd.oasis.opendocument.spreadsheet ods;
+ application/vnd.oasis.opendocument.text odt;
+ application/vnd.openxmlformats-officedocument.presentationml.presentation
+ pptx;
+ application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
+ xlsx;
+ application/vnd.openxmlformats-officedocument.wordprocessingml.document
+ docx;
+ application/vnd.wap.wmlc wmlc;
+ application/wasm wasm;
+ application/x-7z-compressed 7z;
+ application/x-cocoa cco;
+ application/x-java-archive-diff jardiff;
+ application/x-java-jnlp-file jnlp;
+ application/x-makeself run;
+ application/x-ns-proxy-autoconfig pac;
+ application/x-perl pl pm;
+ application/x-pilot prc pdb;
+ application/x-rar-compressed rar;
+ application/x-redhat-package-manager rpm;
+ application/x-sea sea;
+ application/x-shockwave-flash swf;
+ application/x-stuffit sit;
+ application/x-tcl tcl tk;
+ application/x-x509-ca-cert der pem crt;
+ application/x-xpinstall xpi;
+ application/xhtml+xml xhtml;
+ application/xspf+xml xspf;
+ application/zip zip;
+
+ application/octet-stream bin exe dll;
+ application/octet-stream deb;
+ application/octet-stream dmg;
+ application/octet-stream iso img;
+ application/octet-stream msi msp msm;
+
+ audio/basic au snd;
+ audio/midi mid midi kar;
+ audio/mpeg mp3;
+ audio/ogg ogg;
+ audio/x-m4a m4a;
+ audio/x-realaudio ra;
+
+ video/3gpp 3gpp 3gp;
+ video/mp2t ts;
+ video/mp4 mp4;
+ video/mpeg mpeg mpg;
+ video/quicktime mov;
+ video/webm webm;
+ video/x-flv flv;
+ video/x-m4v m4v;
+ video/x-matroska mkv;
+ video/x-mng mng;
+ video/x-ms-asf asx asf;
+ video/x-ms-wmv wmv;
+ video/x-msvideo avi;
+}
diff --git a/httpd/fx/config/routes.kc3 b/httpd/fx/config/routes.kc3
new file mode 100644
index 0000000..11b1f07
--- /dev/null
+++ b/httpd/fx/config/routes.kc3
@@ -0,0 +1,4 @@
+def HTTPd.routes = []
+
+def_route("/fx/", FXController.route)
+def_route("/", static_controller)
diff --git a/httpd/fx/fx b/httpd/fx/fx
new file mode 120000
index 0000000..c25bddb
--- /dev/null
+++ b/httpd/fx/fx
@@ -0,0 +1 @@
+../..
\ No newline at end of file