dev.metalisp.sbt/examples/album.lisp

129 lines
5.3 KiB
Common Lisp
Raw Normal View History

2023-07-15 21:09:40 +02:00
(defpackage cl-sbt-album
(:use :cl)
(:import-from :cl-sbt-grid :container :row :col)
(:import-from :cl-sbt-navbar :navbar :brand :toggler)
2023-07-16 13:58:34 +02:00
(:import-from :cl-sbt :write-string-to-file :with-page)
2023-07-16 11:54:23 +02:00
(:import-from :spinneret :with-html-string)
2023-07-15 21:09:40 +02:00
(:export
2023-07-16 14:10:31 +02:00
:show-album-page
:contact
:about
:header
:main
:footer
:*navbar-header-id*)
(:documentation "The `cl-sbt-album` package provides macros for building an
album-style website page using Bootstrap and Spinneret."))
2023-07-15 21:09:40 +02:00
(in-package :cl-sbt-album)
2023-07-15 22:36:49 +02:00
(defvar *navbar-header-id* "navbarHeader")
2023-07-15 21:09:40 +02:00
2023-07-16 12:11:42 +02:00
(defmacro about ((&key (textbody "secondary")) &body body)
2023-07-16 14:10:31 +02:00
"Generates an HTML 'About' section with the provided content.
TEXTBODY: Specifies the color scheme of the text body. Default is 'secondary'.
BODY: Specifies the HTML content to be included in the 'About' section. This
can be any valid HTML content that spinneret:with-html can parse.
Example usage:
(about () \"This is an about section.\")
; This will generate an 'About' section with secondary color text and the
; provided content."
2023-07-15 21:09:40 +02:00
`(spinneret:with-html
(:h4 "About"
2023-07-16 12:11:42 +02:00
(:p :class ,(concatenate 'string
(if textbody (format nil "text-body-~a" textbody) ""))
2023-07-15 21:09:40 +02:00
,@body))))
(defmacro contact (&rest rest)
2023-07-16 14:10:31 +02:00
"Generates an HTML 'Contact' section with the provided links.
REST: A list of plists, each representing a link. Each plist should contain a
:url and a :label.
Example usage:
(contact (:url \"#\" :label \"Follow on Twitter\")
(:url \"#\" :label \"Like on Facebook\")
(:url \"#\" :label \"Email me\"))
; This will generate a 'Contact' section with three links, each with the
; provided URL and label."
2023-07-15 21:09:40 +02:00
`(spinneret:with-html
(:h4 "Contact")
(:ul :class "list-unstyled"
,@(loop for item in rest
collect (destructuring-bind (&key url label) item
`(:li (:a :class "text-white"
:href ,url
,label)))))))
(defmacro header (&body body)
2023-07-16 13:58:34 +02:00
"Generates an HTML header for the album page.
This macro generates a header with a navigation bar and some predefined
content, including an 'About' section with a description of the album and a
'Contact' section with some dummy contact links.
Additional content can be added to the header by passing it as BODY arguments
to the macro. The BODY content will be included in the header after the
predefined content."
2023-07-15 21:09:40 +02:00
`(spinneret:with-html
2023-07-16 13:58:34 +02:00
(:header (:div :id ,*navbar-header-id*
:class "collapse"
(container ()
(row ()
(col (:sm (8 nil) :md (7 nil) :spacing (:property :p :side :y :size 4))
2023-07-16 14:10:31 +02:00
(about () "Add some information about the album below, the author, or any other background context. Make it a few sentences long so folks can pick up some informative tidbits. Then, link them off to some social networking sites or contact information."))
2023-07-16 13:58:34 +02:00
(col (:sm (8 nil) :md (nil 1))
(contact (:url "#" :label "Follow on Twitter")
(:url "#" :label "Like on Facebook")
(:url "#" :label "Email me"))))))
(navbar (:fluid nil)
(brand () "Album")
(toggler ,*navbar-header-id*))
,@body)))
2023-07-15 21:09:40 +02:00
2023-07-16 11:36:58 +02:00
(defmacro footer ((&key (textbody "secondary") (spacing nil)) &body body)
2023-07-16 10:28:22 +02:00
"Generates an HTML footer with Bootstrap classes.
TEXTBODY: Specifies the color scheme of the text body, default is 'secondary'.
SPACING: A list specifying the Bootstrap spacing class. The list should contain
keyword arguments that can be passed to the cl-sbt-spacing:spacing function.
2023-07-16 11:36:58 +02:00
BODY: Optional. Specifies additional HTML content to be added to the footer.
This can be any valid HTML content that spinneret:with-html can parse.
2023-07-16 10:28:22 +02:00
The footer generated contains fixed content, including a 'Back to top' link and
a short paragraph about Bootstrap.
Example usage:
2023-07-16 11:36:58 +02:00
(footer (:textbody \"primary\" :spacing (:property :p :side :y :size 4))
(:p :class \"custom-class\" \"Custom content here\"))
2023-07-16 10:28:22 +02:00
; This will generate a footer with primary color text and a top/bottom
2023-07-16 11:36:58 +02:00
; padding of size 4. Additionally, a paragraph with class 'custom-class'
; and text 'Custom content here' will be added to the footer."
2023-07-15 21:09:40 +02:00
`(spinneret:with-html
2023-07-16 10:28:22 +02:00
(:footer :class ,(concatenate 'string
(if textbody (format nil "text-body-~a " textbody) "")
(if (null spacing) ""
2023-07-16 21:12:50 +02:00
(apply #'cl-sbt-utility:spacing spacing)))
2023-07-16 10:28:22 +02:00
(container ()
(:p :class "float-end mb-1"
(:a :href "#" "Back to top"))
(:p :class "mb-1"
"Album example is © Bootstrap, but please download and customize it for yourself!")
(:p :class "mb-0"
"New to Bootstrap? "
(:a :href "/" "Visit the homepage")
" or read our "
2023-07-16 11:36:58 +02:00
(:a :href "/docs/5.3/getting-started/introduction/" "getting started guide"))
,@body))))
2023-07-15 21:09:40 +02:00
2023-07-15 22:36:49 +02:00
(defmacro album-page (title &body body)
2023-07-16 13:58:34 +02:00
`(with-page (:title ,title)
(header)
2023-07-16 14:10:31 +02:00
(:main ,@body)
2023-07-16 13:58:34 +02:00
(footer (:spacing (:property :p :side :y :size 5)))))