/Neocity

My Neocity Page

Primary LanguageClojureOtherNOASSERTION

Srcerizder’s Neocity Page

  • Intended as an autistic artistic personal replacement for Linktr.ee
  • This can be thought of as a form of interweb portfolio.
  • It is intentionally dated looking, and minimal. I will not be modernizing this to look like generic_template.css
  • I won’t provide support for any issues on your machine, as this is a pet project.

DISCLAIMER

  • I’m not responsible for any breakage due to my code.
  • If you’re unsure, refer to THE LICENSE to see how seriously I take this.
  • Use with *caution*

Layout of Project

.
|-- LICENSE.txt
|-- README.org
|-- project.clj
|-- resources
|   |-- private
|   |   |-- garden
|   |   |   `-- main.edn
|   |   `-- hiccup
|   |       `-- index.edn
|   `-- public
|       |-- android-chrome-192x192.png
|       |-- android-chrome-512x512.png
|       |-- apple-touch-icon.png
|       |-- favicon-16x16.png
|       |-- favicon-32x32.png
|       |-- favicon.ico
|       `-- img
|           |-- ARROWGRUV.GIF
|           |-- BACKDRP.PNG
|           |-- GOOBYEGRUV.GIF
|           `-- SRCERIZDER.PNG
`-- src
    `-- srcerizder_site
        `-- web.clj

Code Structure

This is my Dependency Declaration, as well as project structure

(defproject srcerizder-site "b1.0"
  :description "My Neocity Page"
  :url "https://izder456.neocities.org"
  :license {:name "WTFPL Version 2 (Modified)"
            :url "https://www.wtfpl.net/"}
  :dependencies [[org.clojure/clojure "1.10.3"]
                 [stasis "2023.06.03"]
                 [ring "1.10.0"]
                 [garden "1.3.10"]
                 [hiccup "2.0.0-RC1"]
                 [optimus "2023-02-08"]]
  :ring {:handler srcerizder-site.web/app}
  :aliases {"build-site" ["run" "-m" "srcerizder-site.web/export"]
            "clean-site" ["run" "-m" "srcerizder-site.web/clean"]
            "run-site" ["ring", "server"]}
  :profiles {:dev {:plugins [[lein-ring "0.12.6"]]}})

This has my export Logic, and Macros

NAMESPACE-DECLARE

Clojure is Java with a lisp, so we need to declare name space and relevant :require values

;; Define Namespace & alias for easy use (bleh, boilerplate...)
(ns srcerizder-site.web
  (:require [ring.middleware.content-type :refer [wrap-content-type]]
            [optimus.assets :as assets]
            [optimus.export]
            [optimus.optimizations :as optimizations]
            [optimus.prime :as optimus]
            [optimus.strategies :refer [serve-live-assets]]
            [clojure.string :as string]
            [clojure.edn :as edn]
            [clojure.java.io :as io]
            [garden.core :as garden]
            [hiccup2.core :as hiccup2]
            [stasis.core :as stasis]))

EDN-DATA-HANDLE

Since my “HTML” and “CSS” are just EDN-Format, I need a way to load that into my export logic

;; Public dir
(def publics "resources/public/")
(def public-styles "resources/public/styles/")

;; Private edn dirs
(def edn-docs "resources/private/hiccup")
(def edn-styles "resources/private/garden")

;; Load in edn files
(defn load-edn [filename]
  (edn/read-string (slurp filename)))

CONVERSION-LOGIC

;; Convert 1 (one) edn doc to html via argument
(defn convert-to-html [edn-filename]
  (let [base-filename (-> edn-filename
                          (.getName)
                          (string/replace #"\.edn$" ""))
        html-filename (str publics base-filename ".html")
        hiccup-data (load-edn edn-filename)
        html (hiccup2/html hiccup-data)]
    (spit html-filename html)))

;; Recurse over a seq of all (any) edn docs and run (convert-to-html) on them
(defn convert-all-to-html [edn-directory]
  (let [edn-files (file-seq (io/file edn-directory))]
    (doseq [edn-file edn-files
            :when (.endsWith
                   (.getName edn-file) ".edn")]
      (convert-to-html edn-file))))

;; Convert 1 (one) edn doc to html via argument
(defn convert-to-css [edn-stylename]
  (let [base-filename (-> edn-stylename
                          (.getName)
                          (string/replace #"\.edn$" ""))
        css-filename (str public-styles base-filename ".css")
        garden-data (load-edn edn-stylename)
        css (garden/css garden-data)]
    (spit css-filename css)))

;; Recurse over a seq of all (any) edn docs and run (convert-to-css) on them
(defn convert-all-to-css [edn-directory]
  (let [edn-styles (file-seq (io/file edn-directory))]
    (doseq [edn-style edn-styles
            :when (.endsWith
                   (.getName edn-style) ".edn")]
      (convert-to-css edn-style))))

ENSURE-DIR-EXIST

I need to ensure that the export dir exists, so if not, we need a way to make it.

  • This function does this
;; Ensure Dir is there, otherwise make it!
(defn ensure-dir [path]
  (let [dir (io/file path)]
    (when-not (.exists dir)
      (.mkdirs dir))))

HANDLE-EXPORTTIME-LOGIC

  1. I need to ensure that the dirs exist where they need to be
  2. then, i need to pull the pages and slurp them into stasis
;; Render hiccup and garden edn maps
(defn final-render []
  (ensure-dir publics)
  (ensure-dir public-styles)
  (convert-all-to-html edn-docs)
  (convert-all-to-css edn-styles))

;; Get page data ready
(defn get-pages []
  (stasis/merge-page-sources
   {:public (stasis/slurp-directory "resources/public" #".*\.(html|css|png|ico|webmanifest)$")}))

;; Pull assets for images and styles
(defn get-assets []
  (assets/load-assets "public" [#"/styles/.*" #"/img/.*\.(PNG|GIF|JPG|JPEG|BMP)"]))

DELETE-LOGIC

  1. I need a way to safely clean delete files, making sure i don’t do a rm -rvf on something I probably forgot about
;; Safe Delete
(defn delete-safe [file-path]
  (if (.exists (io/file file-path))
    (try
      (io/delete-file file-path)
      (catch Exception e (str "Exception caught: " (.getMessage e))))
    false))

;; Recursive delete
(defn delete-dir [dir-path]
  (let [dir-contents (file-seq (io/file dir-path))
        del-files (filter #(.isFile %) dir-contents)]
    (doseq [file del-files]
      (delete-safe (.getPath file)))
    (delete-safe dir-path)))

FINAL-EXPORTTIME-LOGIC

  1. Define export locations
  2. Clean export locations
  3. Finally export my site
;; Define export location
(def export-dir "./dist")
(def export-style-dir "./dist/styles")

;; Clean target
(defn clean []
  (delete-dir export-dir)
  (delete-dir export-style-dir)
  (delete-dir (str publics [#"\.html$"]))
  (delete-dir public-styles))

;; Export Target
(defn export []
  (clean)
  (final-render)
  (ensure-dir export-dir)
  (ensure-dir export-style-dir)
  (let [assets (optimizations/all (get-assets) {})]
    (stasis/empty-directory! export-dir)
    (optimus.export/save-assets assets export-dir)
    (stasis/export-pages (get-pages) export-dir {:optimus-assets assets})))

RING-WEBSERVER-APP

  • for testing
;; Serve for debugging with ring
(def app (-> (stasis/serve-pages get-pages)
             (optimus/wrap get-assets optimizations/all serve-live-assets)
             wrap-content-type))