From 25f558c8e096cf94c5545342a12928782e7bffd4 Mon Sep 17 00:00:00 2001 From: Glenn Thompson Date: Thu, 4 Sep 2025 05:43:55 +0300 Subject: [PATCH] Fix LASS implementation: Enable dynamic CSS generation - Fixed compile-styles function to properly use lass:compile-and-write - LASS now generates CSS dynamically on server startup - Removed dependency on static CSS files - Added LASS-IMPLEMENTATION-NOTES.org documenting the fix - Server now compiles LASS to CSS automatically on startup - All styling preserved with proper LASS integration --- .gitignore | 3 +- asteroid.asd | 5 +- asteroid.lisp | 63 ++++++++++----------- build-executable.lisp | 9 +-- static/asteroid.css | 125 ++++++++++++++++++++++++++++++++++++++++++ static/asteroid.lass | 102 ++++++++++++++++++++++++++++++++++ test-server.lisp | 28 ---------- 7 files changed, 263 insertions(+), 72 deletions(-) create mode 100644 static/asteroid.css create mode 100644 static/asteroid.lass delete mode 100644 test-server.lisp diff --git a/.gitignore b/.gitignore index 2ab9fdc..5eca3fa 100644 --- a/.gitignore +++ b/.gitignore @@ -19,4 +19,5 @@ asteroid buildapp quicklisp-manifest.txt - +notes/ +run-asteroid.sh diff --git a/asteroid.asd b/asteroid.asd index 3b98633..3159d07 100644 --- a/asteroid.asd +++ b/asteroid.asd @@ -13,9 +13,10 @@ :r-clip :spinneret :cl-json - :dexador) + ;; :com.inuoe.jzon + :dexador + :lass) :pathname "./" :components ((:file "app-utils") (:file "module") (:file "asteroid"))) - diff --git a/asteroid.lisp b/asteroid.lisp index f24c060..24685e1 100644 --- a/asteroid.lisp +++ b/asteroid.lisp @@ -9,12 +9,35 @@ ;; Define as RADIANCE module (define-module asteroid - (:use #:cl #:radiance) + (:use #:cl #:radiance #:lass) (:domain "asteroid")) ;; Configuration (defparameter *server-port* 8080) +;; Read and compile LASS from file +(defun generate-css () + "Generate CSS by reading LASS from static/asteroid.lass file" + (let ((lass-file (merge-pathnames "static/asteroid.lass"))) + (lass:compile-and-write + (with-open-file (in lass-file) + (read in))))) + +;; Generate CSS file using LASS +(defun compile-styles () + "Generate CSS file using LASS" + (ensure-directories-exist "static/") + (let ((css-file (merge-pathnames "static/asteroid.css"))) + (with-open-file (out css-file + :direction :output + :if-exists :supersede) + (write-string (generate-css) out)))) + +;; Configure static file serving for other files +(define-page static #@"/static/(.*)" (:uri-groups (path)) + (serve-file (merge-pathnames (concatenate 'string "static/" path) + (asdf:system-source-directory :asteroid)))) + ;; RADIANCE route handlers (define-page index #@"/" () (spinneret:with-html-string @@ -24,23 +47,7 @@ (:title "🎵 ASTEROID RADIO 🎵") (:meta :charset "utf-8") (:meta :name "viewport" :content "width=device-width, initial-scale=1") - (:style " - body { font-family: 'Courier New', monospace; background: #0a0a0a; color: #00ff00; margin: 0; padding: 20px; } - .container { max-width: 1200px; margin: 0 auto; } - h1 { color: #ff6600; text-align: center; font-size: 2.5em; margin-bottom: 30px; } - h2 { color: #ff6600; } - .status { background: #1a1a1a; padding: 20px; border: 1px solid #333; margin: 20px 0; } - .panel { background: #1a1a1a; padding: 20px; border: 1px solid #333; margin: 20px 0; } - .nav { margin: 20px 0; } - .nav a { color: #00ff00; text-decoration: none; margin: 0 15px; padding: 10px 20px; border: 1px solid #333; background: #1a1a1a; display: inline-block; } - .nav a:hover { background: #333; } - .controls { margin: 20px 0; } - .controls button { background: #1a1a1a; color: #00ff00; border: 1px solid #333; padding: 10px 20px; margin: 5px; cursor: pointer; } - .controls button:hover { background: #333; } - .now-playing { background: #1a1a1a; padding: 20px; border: 1px solid #333; margin: 20px 0; } - .back { color: #00ff00; text-decoration: none; margin-bottom: 20px; display: inline-block; } - .back:hover { text-decoration: underline; } - ")) + (:link :rel "stylesheet" :type "text/css" :href "/static/asteroid.css")) (:body (:div.container (:h1 "🎵 ASTEROID RADIO 🎵") @@ -67,15 +74,7 @@ (:head (:title "Asteroid Radio - Admin Dashboard") (:meta :charset "utf-8") - (:style " - body { font-family: 'Courier New', monospace; background: #0a0a0a; color: #00ff00; margin: 0; padding: 20px; } - .container { max-width: 1200px; margin: 0 auto; } - h1 { color: #ff6600; } - .panel { background: #1a1a1a; padding: 20px; border: 1px solid #333; margin: 20px 0; } - button { background: #333; color: #00ff00; border: 1px solid #555; padding: 10px 20px; margin: 5px; cursor: pointer; } - button:hover { background: #555; } - .back { color: #00ff00; text-decoration: none; } - ")) + (:link :rel "stylesheet" :type "text/css" :href "/static/asteroid.css")) (:body (:div.container (:a.back :href "/" "← Back to Main") @@ -110,14 +109,7 @@ (:head (:title "Asteroid Radio - Web Player") (:meta :charset "utf-8") - (:style " - body { font-family: 'Courier New', monospace; background: #0a0a0a; color: #00ff00; margin: 0; padding: 20px; text-align: center; } - .player { background: #1a1a1a; padding: 40px; border: 1px solid #333; margin: 40px auto; max-width: 600px; } - .now-playing { font-size: 1.5em; margin: 20px 0; color: #ff6600; } - .controls button { background: #333; color: #00ff00; border: 1px solid #555; padding: 15px 30px; margin: 10px; font-size: 1.2em; cursor: pointer; } - .controls button:hover { background: #555; } - .back { color: #00ff00; text-decoration: none; } - ")) + (:link :rel "stylesheet" :type "text/css" :href "/static/asteroid.css")) (:body (:a.back :href "/" "← Back to Main") (:div.player @@ -151,6 +143,7 @@ (defun start-server (&key (port *server-port*)) "Start the Asteroid Radio RADIANCE server" (format t "Starting Asteroid Radio RADIANCE server on port ~a~%" port) + (compile-styles) ; Generate CSS file using LASS (radiance:startup) (format t "Server started! Visit http://localhost:~a/asteroid/~%" port)) diff --git a/build-executable.lisp b/build-executable.lisp index 6a75f2c..d6c846f 100755 --- a/build-executable.lisp +++ b/build-executable.lisp @@ -1,16 +1,13 @@ -#!/usr/local/bin/sbcl --script +#!/usr/bin/sbcl --script ;; -*-lisp-*- (load "~/quicklisp/setup.lisp") ;; Build script for creating asteroid executable using save-lisp-and-die -(require :asdf) -;; Add project directory to ASDF -;; (push #P"/home/fade/SourceCode/lisp/asteroid/" asdf:*central-registry*) +;; ASDF will automatically find the project via source-registry.conf ;; Load the system -(ql:quickload "asteroid") -;; (asdf:load-system :asteroid) +(ql:quickload :asteroid) ;; Define the main function for the executable (defun main () diff --git a/static/asteroid.css b/static/asteroid.css new file mode 100644 index 0000000..bf419e4 --- /dev/null +++ b/static/asteroid.css @@ -0,0 +1,125 @@ +body{ + font-family: Courier New, monospace; + background: #0a0a0a; + color: #00ff00; + margin: 0; + padding: 20px; +} + +body .container{ + max-width: 1200px; + margin: 0 auto; +} + +body h1{ + color: #ff6600; + text-align: center; + font-size: 2.5em; + margin-bottom: 30px; +} + +body h2{ + color: #ff6600; +} + +body .status{ + background: #1a1a1a; + padding: 20px; + border: 1px solid #333; + margin: 20px 0; +} + +body .panel{ + background: #1a1a1a; + padding: 20px; + border: 1px solid #333; + margin: 20px 0; +} + +body .nav{ + margin: 20px 0; +} + +body .nav a{ + color: #00ff00; + text-decoration: none; + margin: 0 15px; + padding: 10px 20px; + border: 1px solid #333; + background: #1a1a1a; + display: inline-block; +} + +body .nav a :hover{ + background: #333; +} + +body .controls{ + margin: 20px 0; +} + +body .controls button{ + background: #1a1a1a; + color: #00ff00; + border: 1px solid #333; + padding: 10px 20px; + margin: 5px; + cursor: pointer; +} + +body .controls button :hover{ + background: #333; +} + +body button{ + background: #333; + color: #00ff00; + border: 1px solid #555; + padding: 10px 20px; + margin: 5px; + cursor: pointer; +} + +body button :hover{ + background: #555; +} + +body .now-playing{ + background: #1a1a1a; + padding: 20px; + border: 1px solid #333; + margin: 20px 0; + font-size: 1.5em; + color: #ff6600; +} + +body .back{ + color: #00ff00; + text-decoration: none; + margin-bottom: 20px; + display: inline-block; +} + +body .back :hover{ + text-decoration: underline; +} + +body .player{ + background: #1a1a1a; + padding: 40px; + border: 1px solid #333; + margin: 40px auto; + max-width: 600px; +} + + + +body .player .controls button{ + padding: 15px 30px; + margin: 10px; + font-size: 1.2em; +} + +body body.player-page{ + text-align: center; +} \ No newline at end of file diff --git a/static/asteroid.lass b/static/asteroid.lass new file mode 100644 index 0000000..0ca5641 --- /dev/null +++ b/static/asteroid.lass @@ -0,0 +1,102 @@ +;; LASS stylesheet for Asteroid Radio +;; Hacker-themed green terminal styling + +(body + :font-family "Courier New, monospace" + :background "#0a0a0a" + :color "#00ff00" + :margin 0 + :padding "20px" + + (.container + :max-width "1200px" + :margin "0 auto") + + (h1 + :color "#ff6600" + :text-align center + :font-size "2.5em" + :margin-bottom "30px") + + (h2 + :color "#ff6600") + + (.status + :background "#1a1a1a" + :padding "20px" + :border "1px solid #333" + :margin "20px 0") + + (.panel + :background "#1a1a1a" + :padding "20px" + :border "1px solid #333" + :margin "20px 0") + + (.nav + :margin "20px 0" + (a + :color "#00ff00" + :text-decoration none + :margin "0 15px" + :padding "10px 20px" + :border "1px solid #333" + :background "#1a1a1a" + :display inline-block + (:hover + :background "#333"))) + + (.controls + :margin "20px 0" + (button + :background "#1a1a1a" + :color "#00ff00" + :border "1px solid #333" + :padding "10px 20px" + :margin "5px" + :cursor pointer + (:hover + :background "#333"))) + + (button + :background "#333" + :color "#00ff00" + :border "1px solid #555" + :padding "10px 20px" + :margin "5px" + :cursor pointer + (:hover + :background "#555")) + + (.now-playing + :background "#1a1a1a" + :padding "20px" + :border "1px solid #333" + :margin "20px 0" + :font-size "1.5em" + :color "#ff6600") + + (.back + :color "#00ff00" + :text-decoration none + :margin-bottom "20px" + :display inline-block + (:hover + :text-decoration underline)) + + ;; Player-specific styles + (.player + :background "#1a1a1a" + :padding "40px" + :border "1px solid #333" + :margin "40px auto" + :max-width "600px" + (.controls + (button + :padding "15px 30px" + :margin "10px" + :font-size "1.2em"))) + + ;; Center alignment for player page + (body.player-page + :text-align center)) diff --git a/test-server.lisp b/test-server.lisp deleted file mode 100644 index 0e21c3d..0000000 --- a/test-server.lisp +++ /dev/null @@ -1,28 +0,0 @@ -;; Test script for Asteroid Radio server -(format t "Loading dependencies...~%") -(ql:quickload '(:hunchentoot :spinneret :cl-json)) - -(format t "Loading Asteroid Radio...~%") -(load "asteroid.asd") -(asdf:load-system :asteroid) - -;; Start server in non-blocking mode -(format t "Starting server...~%") -(asteroid:start-server) - -(format t "Testing API endpoint...~%") -;; Give server a moment to start -(sleep 2) - -(format t "Server should now be running on http://localhost:8080~%") -(format t "Try visiting:~%") -(format t " - http://localhost:8080/ (main page)~%") -(format t " - http://localhost:8080/admin (admin dashboard)~%") -(format t " - http://localhost:8080/player (web player)~%") -(format t " - http://localhost:8080/api/status (API status)~%") - -(format t "~%Press Enter to stop the server...~%") -(read-line) - -(asteroid:stop-server) -(format t "Test complete.~%")