From fa3e4e8d9af21f645a9b1f41336a87afcb9e605c Mon Sep 17 00:00:00 2001 From: Alexander Artemenko Date: Sat, 6 Apr 2024 10:27:29 +0300 Subject: [PATCH] Ability to customize index page title and path. --- example/.staticlrc | 4 +- src/index/paginated.lisp | 80 +++++++++++++++++++++++++++++----------- src/user-package.lisp | 6 ++- 3 files changed, 67 insertions(+), 23 deletions(-) diff --git a/example/.staticlrc b/example/.staticlrc index 8fd79a4..65a5443 100644 --- a/example/.staticlrc +++ b/example/.staticlrc @@ -4,7 +4,9 @@ :url "https://example.com/" :pipeline (list (load-content) (filter (:path "ru/") - (paginated-index :target-path #P"ru/") + (paginated-index :target-path #P"ru/" + :page-title-fn (lambda (num) + (fmt "Страница ~A" num))) (rss :target-path #P"ru/blog/rss.xml") (atom :target-path #P"ru/blog/atom.xml")) ;; (filter (:path "ru/" :invert t) diff --git a/src/index/paginated.lisp b/src/index/paginated.lisp index 0a0d987..4e72659 100644 --- a/src/index/paginated.lisp +++ b/src/index/paginated.lisp @@ -16,42 +16,80 @@ (in-package #:staticl/index/paginated) +(deftype function-from-int-to-string () + '(function (integer) (values string &optional))) + + +(deftype function-from-int-to-pathname () + '(function (integer) (values pathname &optional))) + +(declaim (ftype function-from-int-to-string + default-page-title-fn)) + +(defun default-page-title-fn (page-number) + (fmt "Page ~A" page-number)) + + +(declaim (ftype function-from-int-to-pathname + default-page-filename-fn)) + +(defun default-page-filename-fn (page-number) + (let ((name (cond + ((= page-number 1) + "index") + (t + (fmt "page-~A" page-number))))) + (make-pathname :name name + :type "html"))) + + (defclass paginated-index (base-index) - ()) + ((page-filename-fn :initarg :page-filename-fn + :type (or null function-from-int-to-pathname) + :documentation "A callback to change page titles. + Accepts single argument - a page number and should return a pathname relative to the site's root. + By default, it returns index.html for the first page and page-2.html, page-3.html for others. -(defun paginated-index (&rest initargs &key target-path page-size template) - (declare (ignore target-path page-size template)) - (apply #'make-instance 'paginated-index - initargs)) + If site has \"clean urls\" setting enabled, then additional transformation to the pathname will be + applied automatically." + :reader page-filename-fn) + (page-title-fn :initarg :page-title-fn + :type (or null function-from-int-to-string) + :documentation "A callback to change page titles. + Accepts single argument - a page number and should return a string. -(defgeneric make-page-filename (index page-number) - (:documentation "Should return a relative pathname like 2.html or page-2.html.") - (:method ((index paginated-index) page-number) - (let ((name (cond - ((= page-number 1) - "index") - (t - (fmt "page-~A" page-number))))) - (make-pathname :name name - :type "html")))) + For example, here is how you can translate page title into a russian: + ```lisp + (paginated-index :target-path #P\"ru/\" + :page-title-fn (lambda (num) + (fmt \"Страница ~A\" num))) + ``` + " + :reader page-title-fn)) + (:default-initargs + :page-title-fn #'default-page-title-fn + :page-filename-fn #'default-page-filename-fn)) -(defgeneric make-page-title (index page-number) - (:documentation "Should return a string with a title for the page") - (:method ((index paginated-index) page-number) - (fmt "Page ~A" page-number))) + +(defun paginated-index (&rest initargs &key target-path page-size template page-title-fn page-filename-fn) + (declare (ignore target-path page-size template page-title-fn page-filename-fn)) + (apply #'make-instance 'paginated-index + initargs)) (defmethod staticl/pipeline:process-items ((site site) (index paginated-index) content-items) (loop for batch in (serapeum:batches content-items (page-size index)) for page-number upfrom 1 collect (make-instance 'index-page - :title (make-page-title index page-number) + :title (funcall (page-title-fn index) + page-number) :target-path (merge-pathnames ;; TODO: implement clean urls - (make-page-filename index page-number) + (funcall (page-filename-fn index) + page-number) (uiop:ensure-directory-pathname (index-target-path index))) :items batch) into pages diff --git a/src/user-package.lisp b/src/user-package.lisp index 6261bd2..88d780d 100644 --- a/src/user-package.lisp +++ b/src/user-package.lisp @@ -5,7 +5,11 @@ (:import-from #:cl #:list #:t - #:nil) + #:nil + #:lambda + #:let) + (:import-from #:serapeum + #:fmt) ;; API imports (:import-from #:staticl/plugins/sitemap #:sitemap)