summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbd <bdunahu@operationnull.com>2024-07-14 17:16:52 -0600
committerbd <bdunahu@operationnull.com>2024-07-14 17:31:28 -0600
commit733194e8567bc495db88de9b0ae1b228d59572fe (patch)
treeec371e8e393dbda41f24b3f355876b726fc2e8b2
initial commit
-rw-r--r--.gitignore1
-rw-r--r--Makefile11
-rw-r--r--content/assets/favicon.icobin0 -> 3262 bytes
-rw-r--r--content/assets/feed.pngbin0 -> 689 bytes
-rw-r--r--content/assets/raven.pngbin0 -> 45670 bytes
-rw-r--r--content/assets/site.css311
-rw-r--r--content/posts/hello-world.md7
-rw-r--r--src/operationnull/pages.scm69
-rw-r--r--src/operationnull/site.scm35
-rw-r--r--src/operationnull/static.scm24
-rw-r--r--src/operationnull/theme.scm125
11 files changed, 583 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b83d222
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/target/
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..ff35e6d
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,11 @@
+GUILE=guix shell guile haunt -- guile
+
+serve:
+ ${GUILE} -c '((@ (haunt serve web-server) serve) "target/")'
+
+site:
+ ${GUILE} -L ./src -c \
+ '((@ (haunt site) build-site) (@ (operationnull site) main-site))'
+
+clean:
+ rm -rf target/
diff --git a/content/assets/favicon.ico b/content/assets/favicon.ico
new file mode 100644
index 0000000..87bb215
--- /dev/null
+++ b/content/assets/favicon.ico
Binary files differ
diff --git a/content/assets/feed.png b/content/assets/feed.png
new file mode 100644
index 0000000..b3c949d
--- /dev/null
+++ b/content/assets/feed.png
Binary files differ
diff --git a/content/assets/raven.png b/content/assets/raven.png
new file mode 100644
index 0000000..3604202
--- /dev/null
+++ b/content/assets/raven.png
Binary files differ
diff --git a/content/assets/site.css b/content/assets/site.css
new file mode 100644
index 0000000..5309225
--- /dev/null
+++ b/content/assets/site.css
@@ -0,0 +1,311 @@
+body {
+ font-family: 'Open Sans', Helvetica, sans-serif;
+ line-height: 1.5;
+ font-size: 18px;
+ background: #000;
+ color: #aaaabb;
+ margin: 0;
+ border-top: 3px solid #300065;
+}
+
+@media (max-width: 799px) {
+ body {
+ padding: 15px;
+ font-size: .95em;
+ }
+}
+
+body h1,
+body h2,
+body h3,
+body h4 {
+ font-weight: normal;
+ margin: 0;
+ padding: 0;
+ color: #bbbbcc;
+}
+body h1 b,
+body h2 b,
+body h3 b,
+body h4 b {
+ display: block;
+ line-height: 1;
+ font-size: 150%;
+}
+body h1 img,
+body h2 img,
+body h3 img,
+body h4 img {
+ vertical-align: middle;
+ border: 0 none;
+}
+body h1 {
+ font-size: 42px;
+ margin-top: 40px;
+}
+
+body h1 {
+ font-size: 42px;
+ margin-top: 40px;
+}
+.gray {
+ font-weight: lighter;
+ color: gray;
+}
+.black {
+ font-weight: lighter;
+ color: black;
+}
+body h2 {
+ margin-top: 60px;
+ position: relative;
+ font-size: 32px;
+}
+body h3 {
+ font-size: 22px;
+ margin-top: 40px;
+ font-weight: bold;
+}
+body p {
+ text-align: justify;
+}
+
+body a {
+ text-decoration: none;
+ color: #3000a9;
+}
+body a:hover {
+ color: #841076;
+ text-decoration: underline;
+}
+
+a:visited {
+ color: #404040;
+}
+
+body pre {
+ background: white;
+}
+
+body pre.src {
+ overflow-y: auto !important;
+ font-size: 16px;
+}
+
+body code {
+ background: #222;
+ border: 1px solid #333;
+ padding: 0px 4px;
+ color: #ccc;
+ overflow-x: auto;
+ font-size: .9em;
+}
+
+body li {
+ margin-bottom: 1em;
+}
+
+body img {
+ border: 1px solid #ccc;
+ height: auto;
+}
+
+@media (max-width: 800px) {
+ body img {
+ max-width: 100%;
+ }
+}
+
+body img.no-border {
+ border: none;
+}
+
+blockquote {
+ padding-left: 2rem;
+ border-left: 5px solid #eee;
+ font-style: italic;
+}
+
+.feed-icon {
+ padding-left: 1rem;
+}
+
+/* Header */
+
+intro {
+ color: #BBB;
+ text-align: center;
+}
+
+intro h1 {
+ font-size: 42px;
+ font-weight: bold;
+ line-height: 1em;
+ margin: .3em;
+ padding: 0;
+}
+
+intro p {
+ color: #aaa;
+ font-size: 14px !important;
+ text-align: center;
+}
+
+intro img {
+ padding-top: 30px;
+ border-radius: 100%;
+ width: 100px;
+}
+
+nav {
+ text-align: center;
+ margin-top: 30px;
+ border-bottom: 1px solid #e2e2e2;
+ font-size: 12px;
+}
+
+nav ul {
+ list-style: none;
+ padding: 0;
+}
+
+nav li {
+ color: #999;
+ display: inline-block;
+ margin: 0;
+}
+
+nav li:first-child {
+ padding-left: 0;
+}
+
+nav a {
+ display: inline-block;
+ padding-right: 6px;
+ border-radius: 0;
+ font-weight: normal;
+ color: #6a6a6a;
+}
+
+nav a:hover {
+ color: #6a6a6a;
+}
+
+nav a:visited {
+ color: #6a6a6a;
+}
+
+/* Footer */
+
+@media (min-width: 800px) {
+ body article,
+ body footer {
+ margin: 0 auto;
+ max-width: 700px !important;
+ width: 700px !important;
+ }
+}
+
+footer {
+ font-size: 0.8em;
+ line-height: 1.8em;
+ margin-top: 50px;
+ text-align: center;
+ color: #aaa;
+ padding: 15px 0;
+ border-top: 1px solid #e2e2e2;
+}
+
+.fade-text {
+ color: #ddd;
+}
+
+/* Summaries */
+
+.summary {
+ margin-bottom: 3rem;
+}
+
+.summary .date {
+ margin-bottom: 0rem;
+}
+
+.summary p {
+ margin-top: 1rem;
+ margin-bottom: 1rem;
+}
+
+/* Posts */
+
+.date {
+ margin-top: -0.3rem;
+ color: #6a6a6a;
+ font-size: 90%;
+}
+
+.tags {
+ margin-top: -1rem;
+ color: #6a6a6a;
+ font-size: 80%;
+}
+
+.tags ul {
+ display: inline-block;
+ padding-left: 0.5rem;
+}
+
+.tags li {
+ display: inline-block;
+ padding: 0.5rem;
+}
+
+.post img, .centered-image {
+ display: block;
+ max-width: 100%;
+ height: auto;
+ margin: 0 auto;
+ padding: 0px;
+ border-radius: 4px;
+}
+
+.post video {
+ display: block;
+ margin: 0 auto;
+ padding: 0px;
+ max-width: 100%;
+}
+
+.caption {
+ text-align: center;
+ margin: 0;
+ margin-left: 4rem;
+ margin-right: 4rem;
+}
+
+iframe {
+ border: none;
+ width: 100%;
+}
+
+/* Syntax Highlighting */
+
+.syntax-special, .syntax-element {
+ color: #8ac6f2;
+ font-weight: bold;
+}
+
+.syntax-string {
+ color: #95e454;
+}
+
+.syntax-keyword, .syntax-attribute {
+ color: #e5786d;
+}
+
+.syntax-comment {
+ color: #ccc;
+}
+
+.syntax-open, .syntax-close {
+ color: #ccc;
+}
diff --git a/content/posts/hello-world.md b/content/posts/hello-world.md
new file mode 100644
index 0000000..7dfcb0e
--- /dev/null
+++ b/content/posts/hello-world.md
@@ -0,0 +1,7 @@
+title: Hello world!
+date: 2024-07-14 17:00
+tags: hello
+summary: again...
+---
+
+again...
diff --git a/src/operationnull/pages.scm b/src/operationnull/pages.scm
new file mode 100644
index 0000000..1771c8a
--- /dev/null
+++ b/src/operationnull/pages.scm
@@ -0,0 +1,69 @@
+(define-module (operationnull pages)
+ #:export (index-content
+ contact-content
+ gold-content))
+
+
+(define index-content
+ '(article (h2 "Welcome.")
+ (p "operationnull is a site created and run by me, bdunahu. My "
+ (i "real")
+ " name is Benjamin.")
+ (p "My interests often revolve around processing and manipulating text--code generation, interpreters, Norse mythology, traditional sword and sorcery, and GNU Emacs, the ultimate text-based operating system. I graduated from CSU with a B.S. in computer science in Spring 2024.")
+ (p "I've dabbled a bit in poetry/fiction ("
+ (a (@ (href "/pages/gold.html"))
+ "example")
+ "), though I am still an amateur writer. I am working on a short sword and sorcery piece (~10,000 words) about an outlandish werewolf named Gǫndul and her creator---the master-conjurer Gullveig, though I am not sure when it is likely to see the light of day. A few of my personal project can be found on my "
+ (a (@ (href "https://git.operationnull.com/"))
+ "git server")
+ ", all libre.")))
+
+(define contact-content
+ '(article (h2 "Contact")
+ (p "Contact me with inquiries about the content of this site here:")
+ (ul (@ (type "bullet"))
+ (li (b "email: ") "bdunahu @ this domain"))
+ (p "Additionally, these accounts are/belong to me. I am not on other platforms.")
+ (ul (@ (type "bullet"))
+ (li (b "IRC: ") "@ Isaz @ libera.chat")
+ (li (b "matrix: ") "@bdunahu:tchncs.de"))))
+
+(define gold-content
+ '(article (h2 "More Worthless than Gold")
+ (div (@ (class "date"))
+ "Written on Feb 12, 2024 by bdunahu")
+ (br)
+ (div (p (@ (class "verse"))
+ "Wilt beneath branches bent on ill-bound hope"
+ (br)
+ "our watchful wings cast petals of shadows,"
+ (br)
+ "the fervent embrace of triple-knot rope"
+ (br)
+ "seldom slaughter those born of the gallows."
+ (br)
+ (br)
+ "In sacred wellspring bearing a kingdom,"
+ (br)
+ "lowly ancients bargain poison and vice."
+ (br)
+ "Our madman need savor his wisdom;"
+ (br)
+ "to take lore for sight is a witless price."
+ (br)
+ (br)
+ "Wanderer impaled by most faithless knife"
+ (br)
+ "tarnished talons adrift the bleeding red,"
+ (br)
+ "from the icy fibers of self-suffered life"
+ (br)
+ "our king --- "
+ (i "war-maker! all-hater!")
+ " --- has fed."
+ (br)
+ (br)
+ "In burst fetters terror comes to bite,"
+ (br)
+ "and thus conclude the coward's futile plight."
+ (br)))))
diff --git a/src/operationnull/site.scm b/src/operationnull/site.scm
new file mode 100644
index 0000000..084bf1b
--- /dev/null
+++ b/src/operationnull/site.scm
@@ -0,0 +1,35 @@
+(define-module (operationnull site)
+ #:use-module (haunt builder assets)
+ #:use-module (haunt builder atom)
+ #:use-module (haunt builder blog)
+ #:use-module (haunt html)
+ #:use-module (haunt post)
+ #:use-module (haunt reader)
+ #:use-module (haunt reader commonmark)
+ #:use-module (haunt site)
+ #:use-module (operationnull pages)
+ #:use-module (operationnull static)
+ #:use-module (operationnull theme)
+ #:export (main-site))
+
+
+(define %blog-collection
+ `(("Posts" "/posts/index.html" ,posts/reverse-chronological)))
+
+(define main-site
+ (site #:title "operationnull"
+ #:domain "operationnull.com"
+ #:posts-directory "content/posts"
+ #:build-directory "target"
+ #:default-metadata
+ '((author . "bdunahu"))
+ #:readers (list commonmark-reader)
+ #:builders (list (static-page index-content "index.html" "home")
+ (static-page contact-content "pages/contact.html" "contact")
+ (blog #:theme main-theme
+ #:prefix "/posts/"
+ #:collections %blog-collection)
+ (static-page gold-content "pages/gold.html" "More Worthless than Gold")
+ (atom-feed)
+ (atom-feeds-by-tag)
+ (static-directory "content/assets" "assets"))))
diff --git a/src/operationnull/static.scm b/src/operationnull/static.scm
new file mode 100644
index 0000000..25f35e2
--- /dev/null
+++ b/src/operationnull/static.scm
@@ -0,0 +1,24 @@
+(define-module (operationnull static)
+ #:use-module (haunt artifact)
+ #:use-module (haunt reader commonmark)
+ #:use-module (haunt html)
+ #:use-module (haunt builder blog)
+ #:use-module (operationnull theme)
+ #:export (static-page))
+
+
+(define* (static-page page destination title
+ #:key
+ (theme main-theme)
+ (reader commonmark-reader))
+ "Return a builder procedure that reads FILE into SXML, adjusts it
+according to the THEME and serialize to HTML and put it to
+build-directory of the site. DESTINATION is a relative resulting file
+path."
+ (lambda (site posts)
+ (list
+ (serialized-artifact
+ destination
+ (with-layout theme site title page)
+ sxml->html))))
+
diff --git a/src/operationnull/theme.scm b/src/operationnull/theme.scm
new file mode 100644
index 0000000..3129203
--- /dev/null
+++ b/src/operationnull/theme.scm
@@ -0,0 +1,125 @@
+(define-module (operationnull theme)
+ #:use-module (haunt artifact)
+ #:use-module (haunt builder blog)
+ #:use-module (haunt html)
+ #:use-module (haunt post)
+ #:use-module (haunt site)
+ #:use-module (ice-9 match)
+ #:use-module (srfi srfi-19)
+ #:export (main-theme))
+
+(define %cc-by-sa-link
+ '(a (@ (href "https://creativecommons.org/licenses/by-sa/4.0/"))
+ "CC-BY-SA 4.0"))
+
+(define (first-paragraph post)
+ (let loop ((sxml (post-sxml post)))
+ (match sxml
+ (() '())
+ (((and paragraph ('p . _)) . _)
+ (list paragraph))
+ ((head . tail)
+ (cons head (loop tail))))))
+
+(define (stylesheet name)
+ `(link (@ (rel "stylesheet")
+ (href ,(string-append "/assets/" name ".css")))))
+
+(define main-theme
+ (theme #:name "bdunahu"
+ #:layout
+ (lambda (site title body)
+ `((doctype "html")
+ (head
+ (meta (@ (charset "utf-8")))
+ (meta (@ (name "viewport")
+ (content "width=device-width, initial-scale=1")))
+ (link (@ (rel "icon")
+ (type "image/x-icon")
+ (href "/assets/favicon.ico")))
+ (title ,(string-append title " — " (site-title site)))
+ (link (@ (rel "alternate")
+ (type "application/atom+xml")
+ (title "Atom feed")
+ (href "/feed.xml")))
+ ,(stylesheet "site")
+ )
+ (body
+ (intro
+ '(div (@ (class "container"))
+ (img (@ (alt "raven") (class "no-border")
+ (src "/assets/raven.png")))
+ (h1 (span (@ (class "white")) bdunahu))
+ (p "cs graduate student @ "
+ (a (@ (href "https://www.cics.umass.edu/"))
+ "UMass Amherst"))))
+ (nav
+ '(div (@ (class "container"))
+ (ul (li (a (@ (href "https://git.operationnull.com/"))
+ "git"))
+ (li (a (@ (href "/pages/contact.html"))
+ "contact"))
+ (li (a (@ (href "/posts/"))
+ "rand"))
+ (li (a (@ (href "/"))
+ "home")))))
+ ,body
+ (footer (@ (class "footer"))
+ "Copyright © 2024 bdunahu"
+ (br)
+ "Site content available under the " ,%cc-by-sa-link " license "
+ (a (@ (href "https://git.operationnull.com/operationnull.git/"))
+ "here")
+ "."
+ (br)
+ "Last updated on "
+ ,(date->string (current-date) "~b ~d, ~Y")
+ ". Generated with "
+ (a (@ (href "https://dthompson.us/projects/haunt.html"))
+ "Haunt")
+ " and "
+ (a (@ (href "https://gnu.org/software/guile"))
+ "Guile Scheme")
+ "."))))
+ #:post-template
+ (lambda (post)
+ `((article
+ (h3 (@ (class "title")),(post-ref post 'title))
+ (div (@ (class "date"))
+ ,(date->string (post-date post)
+ "~B ~d, ~Y"))
+ (div (@ (class "post"))
+ ,(post-sxml post)))))
+ #:collection-template
+ (lambda (site title posts prefix)
+ (define (post-uri post)
+ (string-append prefix "/" (site-post-slug site post) ".html"))
+
+ `(article (h2 ,title
+ (a (@ (href "/feed.xml"))
+ (img (@ (class "feed-icon") (src "/assets/feed.png")))))
+ ,(map (lambda (post)
+ (let ((uri (post-uri post)))
+ `(article (@ (class "summary"))
+ (h3 (a (@ (href ,uri))
+ ,(post-ref post 'title)))
+ (div (@ (class "date"))
+ ,(date->string (post-date post)
+ "~B ~d, ~Y"))
+ (div (@ (class "post"))
+ ,(first-paragraph post))
+ (a (@ (href ,uri)) "more..."))))
+ posts)))
+ #:pagination-template
+ (lambda (site body previous-page next-page)
+ `(,@body
+ (div (@ (class "paginator"))
+ ,(if previous-page
+ `(a (@ (class "paginator-prev") (href ,previous-page))
+ "← Newer")
+ '())
+ ,(if next-page
+ `(a (@ (class "paginator-next") (href ,next-page))
+ "Older →")
+ '()))))
+ ))