diff --git a/www/build.sh b/www/build.sh new file mode 100755 index 0000000..1bd0437 --- /dev/null +++ b/www/build.sh @@ -0,0 +1,9 @@ +#!/bin/bash +(cd src; hy build.hy) +mkdir -p site/{html,assets,scripts} +cp -r src/output/* site/html +echo 'html generated' +cp -r src/scripts site/ +echo 'scripts copied' +cp -r src/assets site/ +echo 'assets copied' diff --git a/www/src/build.hy b/www/src/build.hy new file mode 100644 index 0000000..6f1341a --- /dev/null +++ b/www/src/build.hy @@ -0,0 +1,30 @@ +(import glob [glob]) +(import os [mkdir]) +(import os.path [isfile :as file? isdir :as dir?]) +(import templates *) +(import utils *) + +(require hyrule.control [defmain]) + +(defmain [] + (when (not (dir? "output")) + (mkdir "output")) + + (for [path (glob "./pages/**/*" :recursive True)] + (when (in "__pycache__" path) + (continue)) + + (cond + (and (dir? path) (not (dir? (.replace path "pages" "output")))) + (do + (print f"creating {path}") + (mkdir (.replace path "pages" "output"))) + + (file? path) + (do + (print f"building {path}") + (setv page-name (.split (cut path 2 -3) "/")) + (with [target (open (+ "./output/" (.join "/" (cut page-name 1 None)) ".html") "w")] + (.write target (form->html + (hy.eval (hy.read (with [source (open path "r")] + (.read source))))))))))) diff --git a/www/src/templates/__init__.hy b/www/src/templates/__init__.hy new file mode 100644 index 0000000..781031b --- /dev/null +++ b/www/src/templates/__init__.hy @@ -0,0 +1,5 @@ +(import .footer [footer]) +(import .header [header]) +(import .page [page]) +(import .comments [comments]) +(import .link [link]) diff --git a/www/src/templates/comments.hy b/www/src/templates/comments.hy new file mode 100644 index 0000000..b11ca8c --- /dev/null +++ b/www/src/templates/comments.hy @@ -0,0 +1,12 @@ +(import urllib.parse [quote-plus]) + +(defn comments [route] + `(section (:class comments) + (h2 comments) + (form (:id comment :method post :action ~f"/comment?route={route}" :autocomplete off) + (textarea (:id comment :name comment :placeholder comment :required True :maxlength 2048)) + (input (:id name :type text :name name :placeholder username :required True :maxlength 32)) + (input (:id website :type text :name site :placeholder "website (not required)" :maxlength 256)) + (input (:id submit :type submit :value post))) + + (~f"$[ls -r ./www/data/comments/{(quote-plus route :safe "")} | xargs -I# cat ./www/data/comments/{(quote-plus route :safe "")}/#]"))) diff --git a/www/src/templates/footer.hy b/www/src/templates/footer.hy new file mode 100644 index 0000000..a18a711 --- /dev/null +++ b/www/src/templates/footer.hy @@ -0,0 +1,18 @@ +(import utils [run]) + +(defn footer [] + `(footer + (div + "page rendered at $[date +%s]" + (br) + "page compiled at " ~(run "date +%s")) + (img (:src "/assets/88x31/natalieee.net.png" :alt "natalieee.net 88x31" :width "88" :height "31")) + (div + (footnote (:style "margin-top: 5px") "all content, with the exception of 88x31 buttons or unless otherwise noted is created by natalie and is licensed under a CC BY-NC-SA 4.0 license.")) + (a (:href "https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en") + (img (:src "/assets/88x31/by-nc-sa.png" :alt "license 88x31" :width "88" :height "31"))) + (footnote (:style "margin-top: 5px") "▖▖▖▖▘▖▖▖▖▘▌▖▖▖▘" + (div (:style "flex-direction: row; width: 14ch; gap: 1ch; margin-right: 5px;") + (a (:href "https://stellophiliac.github.io/roboring/0x6e6174/previous") "<-") + (a (:href "https://stellophiliac.github.io/roboring") "roboring") + (a (:href "https://stellophiliac.github.io/roboring/0x6e6174/next") "->"))))) diff --git a/www/src/templates/header.hy b/www/src/templates/header.hy new file mode 100644 index 0000000..72bb9ca --- /dev/null +++ b/www/src/templates/header.hy @@ -0,0 +1,14 @@ +(defn header [] + `(header + (nav + (ul + (li + (a (:href "/") "natalieee.net")) + (li + (a (:href "./..") "back")) + (li + (a (:href "/html/about-site.html") "about (site)")) + (li + (a (:href "/html/about-natalie.html") "about (natalie)")) + (li + (a (:href "/html/thoughts.html") "thoughts (blog)")))))) diff --git a/www/src/templates/link.hy b/www/src/templates/link.hy new file mode 100644 index 0000000..26c1a11 --- /dev/null +++ b/www/src/templates/link.hy @@ -0,0 +1,2 @@ +(defn link [link [label None]] + `(a (:href ~link) ~(if label label link))) diff --git a/www/src/templates/page.hy b/www/src/templates/page.hy new file mode 100644 index 0000000..b86c7e2 --- /dev/null +++ b/www/src/templates/page.hy @@ -0,0 +1,30 @@ +(import templates.header [header]) +(import templates.footer [footer]) + +(import utils [run hy-env]) +(import random [randint]) + +(defn page [html + [title "natalieee.net"] + [author "natalie roentgen connolly"] + [description ""] + [extra-head None]] + (run "echo > /tmp/footnote_count") + `(html (:lang "en") + (head () + (link (:rel "stylesheet" :href "/assets/style.css" :type "text/css")) + (link (:rel preload :href "/assets/style.css")) + (meta (:http-equiv "content-type" :content "text/html; charset=utf-8")) + (meta (:name "viewport" :content "width=device-width, initial-scale=1")) + (meta (:name "author" :content ~author)) + (meta (:name "fediverse:creator" :content "@0x6e6174@catgirl.cloud")) + ~(when description `(meta (:name "description" :content ~description))) + ~(when description `(meta (:name "og:description" :content ~description))) + (link (:rel "me" :href "https://mastodon.catgirl.cloud/@0x6e6174")) + ~(when extra-head extra-head) + (title ~title)) + (body () + ~(header) + (main () + ~html) + ~(footer)))) diff --git a/www/src/utils.hy b/www/src/utils.hy new file mode 100644 index 0000000..cbe853c --- /dev/null +++ b/www/src/utils.hy @@ -0,0 +1,48 @@ +(import html [escape]) +(import itertools [batched]) +(import subprocess [run :as subprocess/run PIPE]) +(import os [environ :as hy-env]) + +(require hyrule.destructure [setv+]) + +(setv self-closing-tags ['area 'base 'br 'col 'embed 'hr 'img 'input 'link 'meta 'param 'source 'track 'wbr]) + +(defn run [command] + (setv env hy-env) + (setv (get env "PATH") (+ (get hy-env "PATH") ":./scripts")) + (.decode (getattr (subprocess/run command :env env :shell True :stdout PIPE :stderr None) "stdout"))) + +(defn form->html [html] + (when (is html None) + (return "")) + + (cond + (isinstance html str) (str html) + (or (isinstance html int) (isinstance html float)) (str html) + (isinstance html hy.models.Expression) + (cond + (not (isinstance (get html 0) hy.models.Symbol)) + (.join "" (map form->html html)) + + True + (do + (setv+ [tag attrs :& rest] html) + (when (is attrs None) (setv attrs [])) + + (when (len attrs) + (when (not (isinstance (get attrs 0) hy.models.Keyword)) + (do + (setv rest (+ [attrs] rest)) + (setv attrs [])))) + + (when (not (isinstance tag hy.models.Symbol)) + (return "")) + + (.format "<{}{}>{}{}" + (.lower tag) + (+ (if (len attrs) " " "") (.join " " (lfor [k v] (batched attrs :n 2) + f"{(cut (str k) 1 None)}=\"{v}\""))) + (.join "" (map form->html rest)) + (if (not-in tag self-closing-tags) + f"" + ""))))))