/ template-utils.lisp
template-utils.lisp
1 ;;;; template-utils.lisp - CLIP Template Processing Utilities 2 ;;;; Proper CLIP-based template rendering using keyword arguments 3 4 (in-package :asteroid) 5 6 ;; Template directory configuration 7 (defparameter *template-directory* 8 (merge-pathnames "template/" (asdf:system-source-directory :asteroid)) 9 "Base directory for all CLIP templates") 10 11 ;; Template cache for parsed templates 12 (defvar *template-cache* (make-hash-table :test 'equal) 13 "Cache for parsed template DOMs") 14 15 (defun template-path (name) 16 "Build full path to template file. 17 NAME can be either: 18 - Simple name: 'front-page' -> 'template/front-page.ctml' 19 - Path with subdirs: 'partial/now-playing' -> 'template/partial/now-playing.ctml'" 20 (merge-pathnames (format nil "~a.ctml" name) *template-directory*)) 21 22 (defun load-template (name) 23 "Load and parse a template by name without caching. 24 Use this for templates that change frequently during development." 25 (plump:parse (alexandria:read-file-into-string (template-path name)))) 26 27 (defun get-template (template-name) 28 "Load and cache a template file. 29 Use this for production - templates are cached after first load." 30 (or (gethash template-name *template-cache*) 31 (let ((parsed (load-template template-name))) 32 (setf (gethash template-name *template-cache*) parsed) 33 parsed))) 34 35 (defun clear-template-cache () 36 "Clear the template cache (useful during development)" 37 (clrhash *template-cache*)) 38 39 (defun render-template-with-plist (template-name &rest plist) 40 "Render a template with plist-style arguments - CLIP's standard way 41 42 CLIP's process-to-string accepts keyword arguments directly and makes them 43 available via (clip:clipboard key-name) in attribute processors. 44 45 Example: 46 (render-template-with-plist \"admin\" 47 :title \"Admin Dashboard\" 48 :server-status \"🟢 Running\")" 49 (let ((template (get-template template-name))) 50 ;; CLIP's standard approach: pass keywords directly 51 (apply #'clip:process-to-string template plist))) 52 53 ;; Custom CLIP attribute processor for text replacement 54 ;; This is the proper CLIP way - define processors for custom attributes 55 (clip:define-attribute-processor data-text (node value) 56 "Process data-text attribute - replaces node text content with clipboard value 57 Usage: <span data-text=\"key-name\">Default Text</span>" 58 (plump:clear node) 59 (plump:make-text-node node (clip:clipboard value)))