From 1d6bb338948888d3350a1381580b84ca184d5fae Mon Sep 17 00:00:00 2001 From: Glenn Thompson Date: Wed, 10 Sep 2025 11:09:04 +0300 Subject: [PATCH 1/3] Complete CLIP templating migration - Remove all inline HTML from asteroid.lisp - Add CLIP templates: front-page.chtml, admin.chtml, player.chtml - Implement data-text attribute processor for dynamic content - Fix LASS compilation to use read-from-string - Update all route handlers to use clip:process-to-string - Maintain original asteroid radio functionality and styling --- asteroid.css | 125 +++++++++++++++++++++++++++++++++++ asteroid.lisp | 136 +++++++++++++------------------------- template/admin.chtml | 36 ++++++++++ template/front-page.chtml | 74 ++++++++------------- template/player.chtml | 33 +++++++++ 5 files changed, 270 insertions(+), 134 deletions(-) create mode 100644 asteroid.css create mode 100644 template/admin.chtml create mode 100644 template/player.chtml diff --git a/asteroid.css b/asteroid.css new file mode 100644 index 0000000..bf419e4 --- /dev/null +++ b/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/asteroid.lisp b/asteroid.lisp index 24685e1..c198cd8 100644 --- a/asteroid.lisp +++ b/asteroid.lisp @@ -9,19 +9,25 @@ ;; Define as RADIANCE module (define-module asteroid - (:use #:cl #:radiance #:lass) + (:use #:cl #:radiance #:lass #:r-clip) (:domain "asteroid")) ;; Configuration (defparameter *server-port* 8080) -;; Read and compile LASS from file +;; Define CLIP attribute processor for data-text +(clip:define-attribute-processor data-text (node value) + (plump:clear node) + (plump:make-text-node node (clip:clipboard value))) + +;; LASS CSS generation (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 from LASS file" + (lass:compile-and-write + (read-from-string + (alexandria:read-file-into-string + (merge-pathnames "static/asteroid.lass" + (asdf:system-source-directory :asteroid)))))) ;; Generate CSS file using LASS (defun compile-styles () @@ -40,93 +46,45 @@ ;; RADIANCE route handlers (define-page index #@"/" () - (spinneret:with-html-string - (:doctype) - (:html - (:head - (:title "đŸŽĩ ASTEROID RADIO đŸŽĩ") - (:meta :charset "utf-8") - (:meta :name "viewport" :content "width=device-width, initial-scale=1") - (:link :rel "stylesheet" :type "text/css" :href "/static/asteroid.css")) - (:body - (:div.container - (:h1 "đŸŽĩ ASTEROID RADIO đŸŽĩ") - (:div.status - (:h2 "Station Status") - (:p "đŸŸĸ LIVE - Broadcasting asteroid music for hackers") - (:p "Current listeners: 0") - (:p "Stream quality: 128kbps MP3")) - (:div.nav - (:a :href "/admin" "Admin Dashboard") - (:a :href "/player" "Web Player") - (:a :href "/api/status" "API Status")) - (:div - (:h2 "Now Playing") - (:p "Artist: The Void") - (:p "Track: Silence") - (:p "Album: Startup Sounds") - (:p "Duration: ∞"))))))) + (let ((template-path (merge-pathnames "template/front-page.chtml" + (asdf:system-source-directory :asteroid)))) + (clip:process-to-string + (plump:parse (alexandria:read-file-into-string template-path)) + :title "đŸŽĩ ASTEROID RADIO đŸŽĩ" + :station-name "đŸŽĩ ASTEROID RADIO đŸŽĩ" + :status-message "đŸŸĸ LIVE - Broadcasting asteroid music for hackers" + :listeners "0" + :stream-quality "128kbps MP3" + :now-playing-artist "The Void" + :now-playing-track "Silence" + :now-playing-album "Startup Sounds" + :now-playing-duration "∞"))) (define-page admin #@"/admin" () - (spinneret:with-html-string - (:doctype) - (:html - (:head - (:title "Asteroid Radio - Admin Dashboard") - (:meta :charset "utf-8") - (:link :rel "stylesheet" :type "text/css" :href "/static/asteroid.css")) - (:body - (:div.container - (:a.back :href "/" "← Back to Main") - (:h1 "Admin Dashboard") - (:div.panel - (:h2 "Playback Control") - (:button "Play") - (:button "Pause") - (:button "Skip") - (:button "Stop")) - (:div.panel - (:h2 "Library Management") - (:button "Upload Music") - (:button "Manage Playlists") - (:button "Scan Library")) - (:div.panel - (:h2 "Live DJ") - (:button "Go Live") - (:button "End Session") - (:button "Mic Check")) - (:div.panel - (:h2 "System Status") - (:p "Server: Running") - (:p "Database: Not Connected") - (:p "Liquidsoap: Not Running") - (:p "Icecast: Not Running"))))))) + (let ((template-path (merge-pathnames "template/admin.chtml" + (asdf:system-source-directory :asteroid)))) + (clip:process-to-string + (plump:parse (alexandria:read-file-into-string template-path)) + :title "Asteroid Radio - Admin Dashboard" + :server-status "đŸŸĸ Running" + :database-status "🟡 Not Connected" + :liquidsoap-status "🔴 Not Running" + :icecast-status "🔴 Not Running"))) (define-page player #@"/player" () - (spinneret:with-html-string - (:doctype) - (:html - (:head - (:title "Asteroid Radio - Web Player") - (:meta :charset "utf-8") - (:link :rel "stylesheet" :type "text/css" :href "/static/asteroid.css")) - (:body - (:a.back :href "/" "← Back to Main") - (:div.player - (:h1 "đŸŽĩ ASTEROID RADIO PLAYER đŸŽĩ") - (:div.now-playing - (:div "Now Playing:") - (:div "Silence - The Sound of Startup")) - (:div.controls - (:button "â–ļ Play Stream") - (:button "⏸ Pause") - (:button "🔊 Volume")) - (:div - (:p "Stream URL: http://localhost:8000/asteroid") - (:p "Bitrate: 128kbps MP3") - (:p "Status: Offline"))))))) + (let ((template-path (merge-pathnames "template/player.chtml" + (asdf:system-source-directory :asteroid)))) + (clip:process-to-string + (plump:parse (alexandria:read-file-into-string template-path)) + :title "Asteroid Radio - Web Player" + :stream-url "http://localhost:8000/asteroid" + :bitrate "128kbps MP3" + :now-playing-artist "The Void" + :now-playing-track "Silence" + :now-playing-album "Startup Sounds" + :player-status "Stopped"))) -(define-page api/status #@"/api/status" () +(define-page status-api #@"/api/status" () (setf (radiance:header "Content-Type") "application/json") (cl-json:encode-json-to-string `(("status" . "running") diff --git a/template/admin.chtml b/template/admin.chtml new file mode 100644 index 0000000..afb3d19 --- /dev/null +++ b/template/admin.chtml @@ -0,0 +1,36 @@ + + + + Asteroid Radio - Admin Dashboard + + + + + +
+

đŸŽ›ī¸ ADMIN DASHBOARD

+ +
+
+

Server Status

+

đŸŸĸ Running

+
+
+

Database Status

+

🟡 Not Connected

+
+
+

Liquidsoap Status

+

🔴 Not Running

+
+
+

Icecast Status

+

🔴 Not Running

+
+
+
+ + diff --git a/template/front-page.chtml b/template/front-page.chtml index 421e221..6cb91f0 100644 --- a/template/front-page.chtml +++ b/template/front-page.chtml @@ -1,48 +1,32 @@ - - - đŸŽĩ ASTEROID RADIO đŸŽĩ - - - - - -
-

đŸŽĩ ASTEROID RADIO đŸŽĩ

-
-

Station Status

-

đŸŸĸ LIVE - Broadcasting asteroid music for hackers -

Current listeners: 0 -

Stream quality: 128kbps MP3 -

- -
-

Now Playing

-

Artist: The Void -

Track: Silence -

Album: Startup Sounds -

Duration: ∞ -

+ + + đŸŽĩ ASTEROID RADIO đŸŽĩ + + + + + +
+

đŸŽĩ ASTEROID RADIO đŸŽĩ

+
+

Station Status

+

đŸŸĸ LIVE - Broadcasting asteroid music for hackers

+

Current listeners: 0

+

Stream quality: 128kbps MP3

+
+ +
+

Now Playing

+

Artist: The Void

+

Track: Silence

+

Album: Startup Sounds

+

Duration: ∞

+
- + diff --git a/template/player.chtml b/template/player.chtml new file mode 100644 index 0000000..ebbea80 --- /dev/null +++ b/template/player.chtml @@ -0,0 +1,33 @@ + + + + Asteroid Radio - Web Player + + + + + +
+

đŸŽĩ WEB PLAYER

+ +
+
+

Now Playing

+

Artist: The Void

+

Track: Silence

+

Album: Startup Sounds

+
+
+ + +

Stream: http://localhost:8000/asteroid

+

Quality: 128kbps MP3

+

Status: Stopped

+
+
+
+ + From f1193904594eb59cbd4bbc648da1a86d95a9ad54 Mon Sep 17 00:00:00 2001 From: Glenn Thompson Date: Wed, 10 Sep 2025 11:20:51 +0300 Subject: [PATCH 2/3] Fix API status endpoint and update navigation - Change API endpoint from /api/status to /status to avoid RADIANCE API call interpretation - Update navigation link in front-page.chtml to point to new /status endpoint - API now returns proper JSON instead of 500 error --- asteroid.css | 125 -------------------------------------- asteroid.lisp | 2 +- template/front-page.chtml | 2 +- 3 files changed, 2 insertions(+), 127 deletions(-) delete mode 100644 asteroid.css diff --git a/asteroid.css b/asteroid.css deleted file mode 100644 index bf419e4..0000000 --- a/asteroid.css +++ /dev/null @@ -1,125 +0,0 @@ -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/asteroid.lisp b/asteroid.lisp index c198cd8..7a32ad1 100644 --- a/asteroid.lisp +++ b/asteroid.lisp @@ -84,7 +84,7 @@ :now-playing-album "Startup Sounds" :player-status "Stopped"))) -(define-page status-api #@"/api/status" () +(define-page status-api #@"/status" () (setf (radiance:header "Content-Type") "application/json") (cl-json:encode-json-to-string `(("status" . "running") diff --git a/template/front-page.chtml b/template/front-page.chtml index 6cb91f0..14ffa8c 100644 --- a/template/front-page.chtml +++ b/template/front-page.chtml @@ -18,7 +18,7 @@

Now Playing

From 526ae010e94a3cea0fa4dd6d652ba24cc810fb8e Mon Sep 17 00:00:00 2001 From: Glenn Thompson Date: Wed, 10 Sep 2025 17:42:23 +0300 Subject: [PATCH 3/3] Add build-sbcl.sh to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 5eca3fa..e869ad8 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,4 @@ buildapp quicklisp-manifest.txt notes/ run-asteroid.sh +build-sbcl.sh