dev.metalisp.sbt/src/main.lisp

227 lines
6.6 KiB
Common Lisp
Raw Normal View History

2024-03-30 07:46:39 +01:00
;;;; -*- mode: lisp; coding: utf-8; fill-column: 84; indent-tabs-mode: nil; -*-
2024-02-05 18:34:46 +01:00
;;;; main.lisp
;;;; Provide general functions.
2024-03-30 07:46:39 +01:00
2023-11-25 09:59:03 +01:00
(defpackage dev.metalisp.sbt
2023-07-01 16:30:10 +02:00
(:use :cl)
(:export
2024-01-28 19:29:34 +01:00
:*l10n*
:find-l10n
2024-01-25 16:07:26 +01:00
:*use-cdn*
:*cdn-css-url*
:*cdn-js-url*
2024-01-28 13:03:35 +01:00
:*local-css-url*
:*local-js-url*
2024-01-25 16:07:26 +01:00
:*bs-version*
:*color-theme*
2024-03-08 21:50:14 +01:00
:download-bs-css
:download-bs-js
2024-01-26 16:30:01 +01:00
:write-html-to-file
2024-03-30 07:46:39 +01:00
:with-page
:remove-special-chars
:clean-form-str
:build-name-str
:build-value-str
:build-value-prop-str
:build-class-str
:build-id-str))
2023-07-01 16:30:10 +02:00
2023-11-25 09:59:03 +01:00
(in-package :dev.metalisp.sbt)
2023-07-03 14:43:58 +02:00
2024-03-08 21:50:14 +01:00
(defparameter spinneret:*fill-column* 120)
2023-07-16 13:57:42 +02:00
2024-01-25 16:07:26 +01:00
(defparameter *bs-version* "5.3.2")
(defparameter *use-cdn* t)
(defparameter *cdn-css-url*
(concatenate 'string
"https://cdn.jsdelivr.net/npm/bootstrap@"
*bs-version*
"/dist/css/bootstrap.min.css"))
(defparameter *cdn-js-url*
(concatenate 'string
"https://cdn.jsdelivr.net/npm/bootstrap@"
*bs-version*
"/dist/js/bootstrap.bundle.min.js"))
2024-03-06 22:12:13 +01:00
(defparameter *bs-path*
(concatenate 'string
"public/"
*bs-version*
"/"))
2024-01-26 16:30:01 +01:00
(defparameter *local-css-url*
2024-03-06 22:12:13 +01:00
(concatenate 'string
*bs-path*
"bootstrap.min.css"))
2024-01-26 16:30:01 +01:00
(defparameter *local-js-url*
2024-03-06 22:12:13 +01:00
(concatenate 'string
*bs-path*
"bootstrap.bundle.min.js"))
2024-01-26 16:30:01 +01:00
2024-01-25 16:07:26 +01:00
(defparameter *color-theme* "dark")
2024-01-28 13:00:56 +01:00
(defun bs-css-url ()
2024-01-26 16:30:01 +01:00
(if *use-cdn*
*cdn-css-url*
*local-css-url*))
2024-01-28 13:00:56 +01:00
(defun bs-js-url ()
2024-01-26 16:30:01 +01:00
(if *use-cdn*
*cdn-js-url*
*local-js-url*))
2024-01-25 16:07:26 +01:00
(defun download-file (url directory)
"Downloads a file from a given URL and saves it to the specified directory."
(let* ((filename (car (last (uiop:split-string url :separator "/"))))
(filepath (merge-pathnames filename directory)))
2024-01-25 19:01:54 +01:00
(ensure-directories-exist directory)
2024-03-06 22:12:13 +01:00
(let ((content (dex:get url)))
(with-open-file (stream filepath
:direction :output
:if-exists :supersede
:if-does-not-exist :create)
(write-string content stream)))
2024-01-25 16:07:26 +01:00
filepath))
(defmacro define-download-function (name url directory)
`(defun ,name (&optional (directory ,directory))
(download-file ,url directory)))
(define-download-function download-bs-css *cdn-css-url* *bs-path*)
(define-download-function download-bs-js *cdn-js-url* *bs-path*)
2024-03-06 22:12:13 +01:00
2024-03-30 07:57:29 +01:00
(defun write-html-str-to-file (filename string
&key (lang "en") (style :tree) (fc 120))
2023-08-25 15:10:01 +02:00
(let ((spinneret:*html-lang* lang)
(spinneret:*html-style* style)
(spinneret:*fill-column* fc))
(with-open-file (stream filename :direction :output :if-exists :supersede)
(write-string string stream))))
2024-01-26 16:30:01 +01:00
2024-03-30 07:57:29 +01:00
(defmacro with-page ((&key meta (title "Web page") main-con add-css-urls
add-js-urls)
&body body)
2024-03-03 12:14:31 +01:00
"This macro simplifies the process of creating an HTML web page.
META: The meta-information for the web page.
TITLE: Specifies the title of the web page. Defaults to 'Web page'.
2024-03-27 11:13:32 +01:00
MAIN-CON: If t add css class `container` to <main>.
2024-03-03 12:14:31 +01:00
ADD-CSS-URLS: An optional parameter for additional CSS file URLs.
ADD-JS-URLS: An optional parameter for additional JavaScript file URLs.
BODY: Denotes the markup for the body of the web page.
Example usage:
(with-page (:meta (:author \"John Doe\") :title \"My Page\" :main-con t) \"foo\")"
2024-01-26 16:30:01 +01:00
`(spinneret:with-html
(:doctype)
(:html :data-bs-theme ,*color-theme*
(:head (:meta :charset "utf-8")
2024-03-30 07:57:29 +01:00
(:meta :name "viewport"
:content "width=device-width, initial-scale=1")
2024-01-26 16:30:01 +01:00
,@(loop for (key value) on meta by #'cddr
2024-01-26 22:23:29 +01:00
collect `(:meta :name
,(string-downcase (symbol-name key))
:content ,(getf meta key)))
2024-01-26 16:30:01 +01:00
(:title ,title)
2024-01-28 13:00:56 +01:00
(:link :type "text/css" :rel "stylesheet" :href ,(bs-css-url))
2024-01-26 16:30:01 +01:00
,@(loop for url in add-css-urls
2024-03-30 07:57:29 +01:00
collect `(:link :type "text/css"
2024-03-30 17:46:36 +01:00
:rel "stylesheet" :href ,url)))
2024-01-26 16:30:01 +01:00
(:body (:h1 :class "visually-hidden" ,title)
2024-03-30 17:46:36 +01:00
(:main ,@(if main-con (list :class "container") nil) ,@body)
2024-01-26 16:30:01 +01:00
2024-03-30 17:46:36 +01:00
(:script :src ,(bs-js-url))
,@(loop for url in add-js-urls
collect `(:script :src ,url))))))
2024-03-30 07:46:39 +01:00
(defun remove-special-chars (str)
"Removes all special characters from the string STR except numbers and alphabets.
STR: The input string from which special characters need to be removed.
Example:
(remove-special-chars \"a1b!@#$%^&*()c2\") will return \"a1bc2\"
Returns:
A new string with special characters removed."
2024-03-30 17:46:48 +01:00
(remove-if-not (lambda (char)
(or (alpha-char-p char) (digit-char-p char)))
2024-03-30 07:46:39 +01:00
str))
(defun clean-form-str (str)
"Cleans a form string for use as a name or identifier.
STR: The string to clean. Removes leading and trailing spaces, replaces spaces
with dashes, and converts to lowercase.
Returns:
A new string which can be used as HTML class."
(string-downcase (substitute #\- #\Space (string-trim '(#\Space) str))))
(defun build-name-str (name)
2024-03-30 07:57:29 +01:00
"Builds a standardized string by adding a 'group-' prefix and applying cleaning
functions.
2024-03-30 07:46:39 +01:00
NAME: The initial name string.
Returns:
A new standardized string."
(concatenate 'string "group-" (clean-form-str name)))
(defun build-value-str (value)
"Trims leading and trailing spaces from the given value string.
VALUE: The string to be cleaned.
Returns:
A new string without leading and trailing spaces."
(string-trim '(#\Space) value))
(defun build-value-prop-str (value)
"Builds a value property string by applying various cleaning functions.
VALUE: The initial value string.
Returns:
A new value property string."
(clean-form-str (build-value-str value)))
(defun build-class-str (class name)
2024-03-30 07:57:29 +01:00
"Builds a class string by concatenating 'form-check-label' and a standardized
name string.
2024-03-30 07:46:39 +01:00
CLASS: Corresponding class property.
NAME: The initial name string.
Returns:
A new class string."
(concatenate 'string class " " (build-name-str name)))
(defun build-id-str (name value)
2024-03-30 07:57:29 +01:00
"Builds an ID string by concatenating a standardized name string and a sanitized
value property string.
2024-03-30 07:46:39 +01:00
NAME: The initial name string.
VALUE: The initial value string.
Returns:
A new ID string."
(concatenate 'string
(build-name-str name)
"-"
(remove-special-chars (build-value-prop-str value))))