From a6e2c99b62e51b351e21b84be7668f820b72eaf8 Mon Sep 17 00:00:00 2001 From: James Brechtel Date: Sat, 20 Jun 2026 17:55:33 -0400 Subject: [PATCH] feat: restyle index page with Pico CSS and emoji glyphs --- spine.el | 116 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 75 insertions(+), 41 deletions(-) diff --git a/spine.el b/spine.el index e9b792c..0fdf171 100644 --- a/spine.el +++ b/spine.el @@ -123,7 +123,14 @@ Returns nil if the file is missing or cannot be parsed." (defun spine-render-index (books &optional selected-id) "Render the index page HTML for BOOKS, expanding the book matching SELECTED-ID." (let ((order '("WANT" "READING" "READ" "ABANDONED")) - (grouped (make-hash-table :test 'equal))) + (grouped (make-hash-table :test 'equal)) + (total 0) + (reading-count 0)) + ;; Count totals + (dolist (book books) + (cl-incf total) + (when (equal "READING" (plist-get book :status)) + (cl-incf reading-count))) ;; Group books by status (dolist (book books) (let* ((status (or (plist-get book :status) "WANT"))) @@ -133,38 +140,65 @@ Returns nil if the file is missing or cannot be parsed." (insert "\n\n\n") (insert "\n") (insert "\n") - (insert "Spine\n\n\n") - (insert "
\n") - (insert "
Spine
\n") + (insert "Spine\n") + (insert "\n") + (insert "\n") + (insert "\n\n") + (insert "
\n") + (insert "
\n") + (insert (format "
spine" + "%d books ยท %d reading
\n" + total reading-count)) ;; Each group in order (dolist (status order) (let ((group-books (nreverse (gethash status grouped)))) (when group-books - (insert (format "
%s (%d)
\n" + (insert (format "

%s

%d
\n" status (length group-books))) (dolist (book group-books) (let ((selected (equal (plist-get book :id) selected-id))) - (insert (format "
\n" - (if selected " selected" ""))) - ;; Format glyph + (insert (format "
\n" + (if selected " spine-selected" ""))) + ;; Format glyph (emoji) (let ((fmt (plist-get book :format))) - (insert (format "%s\n" - (cond ((equal fmt "hardcover") "[H]") - ((equal fmt "ebook") "[E]") - ((equal fmt "audiobook") "[A]") + (insert (format "%s\n" + (cond ((equal fmt "hardcover") "๐Ÿ“–") + ((equal fmt "ebook") "๐Ÿ“ฑ") + ((equal fmt "audiobook") "๐ŸŽง") (t ""))))) ;; Title + author - (insert "") + (insert "") (insert (spine--h (plist-get book :title))) (let ((author (plist-get book :author))) (when author - (insert (format " %s" + (insert (format " %s" (spine--h author))))) (insert "\n") ;; Tags (let ((tags (plist-get book :tags))) (when tags - (insert (format "%s\n" + (insert (format "%s\n" (mapconcat (lambda (tag) (concat ":" tag ":")) tags " "))))) ;; Recommendation trail @@ -172,42 +206,42 @@ Returns nil if the file is missing or cannot be parsed." (rec-note (plist-get book :rec_note))) (when (and rec-by (> (length rec-by) 0)) (insert - (format "%s%s\n" + (format "%s%s\n" (spine--h rec-by) (if (and rec-note (> (length rec-note) 0)) (concat ": " (spine--h rec-note)) ""))))) ;; Status pill (let ((status (or (plist-get book :status) "WANT"))) - (insert (format "%s\n" - (downcase status) status))) + (insert (format "%s\n" + (downcase status) (downcase status)))) ;; Expanded detail (when selected - (insert "
\n") + (insert "
\n") (dolist (note (plist-get book :notes)) - (insert (format - "
[%s] %s
\n" - (spine--h (car note)) - (spine--h (cadr note))))) - (let ((rating (plist-get book :rating))) - (when (and rating (> (length rating) 0)) - (insert (format "
Rating: %s/5
\n" - (spine--h rating))))) - (let ((isbn (plist-get book :isbn))) - (when (and isbn (> (length isbn) 0)) - (insert (format "
ISBN: %s
\n" - (spine--h isbn))))) - (let ((fmt (plist-get book :format))) - (when (and fmt (> (length fmt) 0)) - (insert (format "
Format: %s
\n" - (spine--h fmt))))) - (let ((added (plist-get book :added))) - (when (and added (> (length added) 0)) - (insert (format "
Added: %s
\n" - (spine--h added))))) - (insert "
\n")) + (insert (format "

[%s] %s

\n" + (spine--h (car note)) + (spine--h (cadr note))))) + (let ((parts nil)) + (let ((rating (plist-get book :rating))) + (when (and rating (> (length rating) 0)) + (push (format "Rating: %s/5" (spine--h rating)) parts))) + (let ((isbn (plist-get book :isbn))) + (when (and isbn (> (length isbn) 0)) + (push (format "ISBN: %s" (spine--h isbn)) parts))) + (let ((fmt (plist-get book :format))) + (when (and fmt (> (length fmt) 0)) + (push (format "Format: %s" (spine--h fmt)) parts))) + (let ((added (plist-get book :added))) + (when (and added (> (length added) 0)) + (push (format "Added: %s" (spine--h added)) parts))) + (when parts + (insert (format "\n" + (mapconcat #'identity (nreverse parts) " ยท "))))) + (insert "\n")) (insert "
\n")))))) - (insert "
\n\n\n") + (insert "
\n") + (insert "
\n\n\n") (buffer-string)))) (defun spine-render-empty-state ()