This commit is contained in:
Swrup 2024-09-26 02:15:54 +02:00
commit 9596dde0e4
14 changed files with 281 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
_build

43
.ocamlformat Normal file
View file

@ -0,0 +1,43 @@
version=0.26.2
assignment-operator=end-line
break-cases=fit
break-fun-decl=wrap
break-fun-sig=wrap
break-infix=wrap
break-infix-before-func=false
break-separators=before
break-sequences=true
cases-exp-indent=2
cases-matching-exp-indent=normal
doc-comments=before
doc-comments-padding=2
doc-comments-tag-only=default
dock-collection-brackets=false
exp-grouping=preserve
field-space=loose
if-then-else=compact
indicate-multiline-delimiters=space
indicate-nested-or-patterns=unsafe-no
infix-precedence=indent
leading-nested-match-parens=false
let-and=sparse
let-binding-spacing=compact
let-module=compact
margin=80
max-indent=2
module-item-spacing=sparse
ocaml-version=4.14.0
ocp-indent-compat=false
parens-ite=false
parens-tuple=always
parse-docstrings=true
sequence-blank-line=preserve-one
sequence-style=terminator
single-case=compact
space-around-arrays=true
space-around-lists=true
space-around-records=true
space-around-variants=true
type-decl=sparse
wrap-comments=false
wrap-fun-args=true

2
Makefile Normal file
View file

@ -0,0 +1,2 @@
run:
dune exec src/main.exe

4
README.md Normal file
View file

@ -0,0 +1,4 @@
# template for drame website
- use htmlit instead of tyxml
- single lang

2
config.scfg Normal file
View file

@ -0,0 +1,2 @@
port 3696
path_to_images TODO/src/img/

33
drame_template.opam Normal file
View file

@ -0,0 +1,33 @@
# This file is generated by dune, edit dune-project instead
opam-version: "2.0"
synopsis: "A short synopsis"
description: "A longer description"
maintainer: ["Maintainer Name"]
authors: ["Author Name"]
license: "LICENSE"
tags: ["topics" "to describe" "your" "project"]
homepage: "https://github.com/username/reponame"
doc: "https://url/to/documentation"
bug-reports: "https://github.com/username/reponame/issues"
depends: [
"ocaml"
"dune" {>= "3.15"}
"drame"
"htmlit"
"odoc" {with-doc}
]
build: [
["dune" "subst"] {dev}
[
"dune"
"build"
"-p"
name
"-j"
jobs
"@install"
"@runtest" {with-test}
"@doc" {with-doc}
]
]
dev-repo: "git+https://github.com/username/reponame.git"

31
dune-project Normal file
View file

@ -0,0 +1,31 @@
(lang dune 3.15)
(name drame_template)
(generate_opam_files true)
(source
(github username/reponame))
(authors "Author Name")
(maintainers "Maintainer Name")
(license LICENSE)
(documentation https://url/to/documentation)
(package
(name drame_template)
(synopsis "A short synopsis")
(description "A longer description")
(depends
ocaml
dune
drame
htmlit
)
(tags
(topics "to describe" your project)))
; See the complete stanza docs at https://dune.readthedocs.io/en/stable/dune-files.html#dune-project

14
src/app.ml Normal file
View file

@ -0,0 +1,14 @@
module App_id = struct
let qualifier = "org"
let organization = "TODO"
let application = "drame_template"
end
include Drame.Server.Make (App_id)
let path_to_images =
match Scfg.Query.get_dir "path_to_images" config with
| None -> failwith "missing path_to_images in configuration"
| Some dir -> Scfg.Query.get_param_exn 0 dir

15
src/assets/css/style.css Normal file
View file

@ -0,0 +1,15 @@
:root {
--bg: #FFFFFF;
--fg: #000000;
}
html {
background-color: var(--bg);
color: var(--fg);
}
body {
}
nav {
}

22
src/dune Normal file
View file

@ -0,0 +1,22 @@
(executable
(public_name web_template)
(name main)
(libraries drame htmlit))
(rule
(target assets.ml)
(deps
(source_tree assets))
(action
(with-stdout-to
%{null}
(run ocaml-crunch -m plain assets -o %{target}))))
(rule
(target data.ml)
(deps
(source_tree data))
(action
(with-stdout-to
%{null}
(run ocaml-crunch -m plain data -o %{target}))))

8
src/home.ml Normal file
View file

@ -0,0 +1,8 @@
open Htmlit
let get request =
let title = "Home" in
let h1 = El.h1 [ El.txt title ] in
let txt = El.txt "Welcome to my home page" in
let doc = Template.render request ~styles:[] ~title [ h1; txt ] in
Ok (Drame.Content.Html doc)

79
src/main.ml Normal file
View file

@ -0,0 +1,79 @@
open Drame
let get_img =
let forbidden_characters =
let tbl = Hashtbl.create 16 in
Array.iter (fun c -> Hashtbl.add tbl c ()) [| '.'; '/'; '\\' |];
tbl
in
let allowed_extensions =
let tbl = Hashtbl.create 16 in
Array.iter (fun e -> Hashtbl.add tbl e ()) [| ".jpeg"; ".png"; ".gif" |];
tbl
in
fun ~filename request ->
let extension = Filename.extension filename in
let without_extension = Filename.chop_extension filename in
if
String.exists (Hashtbl.mem forbidden_characters) without_extension
|| (not @@ Hashtbl.mem allowed_extensions extension)
then
let title = Format.sprintf "Invalid filename: %s." filename in
let doc = Template.render request ~title [] in
Error (Status.Bad_request, doc)
else
let path = Filename.concat App.path_to_images filename in
let chan = open_in_bin path in
let len = in_channel_length chan in
let s = Bytes.create len in
Fun.protect
~finally:(fun () -> close_in chan)
(fun () ->
assert (len <= Sys.max_string_length);
really_input chan s 0 len );
let content = Bytes.unsafe_to_string s in
let mimetype =
match extension with
| ".jpeg" -> Mimetype.Image_jpeg
| ".png" -> Mimetype.Image_png
| ".gif" -> Mimetype.Image_gif
| _ -> assert false
in
Ok (Content.Unsafe { content; mimetype })
let get_asset ~filename request =
match Assets.read filename with
| None ->
let title = Format.sprintf "Invalid filename: %s." filename in
let doc = Template.render request ~title [] in
Error (Status.Bad_request, doc)
| Some content -> (
let extension = Filename.extension filename in
match extension with
| ".css" -> Ok (Content.Unsafe { mimetype = Mimetype.Text_css; content })
| ".ttf" -> Ok (Content.Unsafe { mimetype = Mimetype.Font_ttf; content })
| _ -> assert false )
let get_favicon request =
let title = "The favicon is not where you think it is!" in
let h1 = Htmlit.El.h1 [ Htmlit.El.txt title ] in
let doc = Template.render request ~title [ h1 ] in
Error (Status.Moved_permanently Sitemap.favicon, doc)
let not_found request =
let title = "Not found" in
let h1 = Htmlit.El.h1 [ Htmlit.El.txt title ] in
let doc = Template.render request ~title [ h1 ] in
Error (Status.Not_found, doc)
let handler = function
| [| "assets"; "css"; filename |] ->
get_asset ~filename:(Format.sprintf "css/%s" filename)
| [| "assets"; "fonts"; filename |] ->
get_asset ~filename:(Format.sprintf "fonts/%s" filename)
| [| "assets"; "img"; filename |] -> get_img ~filename
| [| "favicon.ico" |] -> get_favicon
| [||] -> Home.get
| _ -> not_found
let () = App.run ~handler

9
src/sitemap.ml Normal file
View file

@ -0,0 +1,9 @@
let img name = Format.sprintf "/assets/img/%s" name
let script name = Format.sprintf "/assets/js/%s" name
let style name = Format.sprintf "/assets/css/%s" name
let favicon = img "favicon.png"
let home = "/"

18
src/template.ml Normal file
View file

@ -0,0 +1,18 @@
open Htmlit
let render _request ?(scripts = []) ?(styles = []) ~title content =
let favicon = El.link ~at:[ At.rel "icon"; At.href Sitemap.favicon ] () in
let meta_desc =
El.meta ~at:[ At.name "description"; At.content "TODO site desciption" ] ()
in
let meta_keys =
El.meta ~at:[ At.name "keywords"; At.content "TODO site desciption" ] ()
in
let more_head = El.splice [ favicon; meta_desc; meta_keys ] in
let header = El.header [ El.nav [] ] in
let main = El.main content in
let footer = El.footer [] in
let body = El.body [ header; main; footer ] in
let page = El.page ~lang:"en" ~styles ~scripts ~more_head ~title body in
let doc = El.to_string ~doctype:true page in
Drame.Content.Unsafe_doc doc