diff --git a/hssg.asd b/hssg.asd index 0b5eabd..f84c11d 100644 --- a/hssg.asd +++ b/hssg.asd @@ -59,4 +59,6 @@ (:file "template") (:file "reader") (:module "readers" - :components ((:file "lisp"))))))))) + :components ((:file "lisp"))) + (:module "artifacts" + :components ((:file "compound"))))))))) diff --git a/src/blog/artifacts/classes.lisp b/src/blog/artifacts/classes.lisp index 1909552..b78bf02 100644 --- a/src/blog/artifacts/classes.lisp +++ b/src/blog/artifacts/classes.lisp @@ -48,7 +48,7 @@ :documentation "Base template to apply to all pages") (initial :initarg :initial :initform '() :type list :documentation "Initial metadata for all pages.") - (static :initform (make-instance 'hssg:compound-artifact) + (static :initform (hssg:make-compound-artifact) :documentation "Static files which will be added to the blog verbatim.")) (:documentation "Artifact which represents an entire blog.")) diff --git a/src/blog/facade.lisp b/src/blog/facade.lisp index 3913693..41f22bf 100644 --- a/src/blog/facade.lisp +++ b/src/blog/facade.lisp @@ -118,13 +118,11 @@ (with-slots ((static hssg.blog.artifacts:static) (output-dir hssg.blog.artifacts:output)) blog - (with-slots ((artifacts hssg:artifacts)) - static - (let ((artifact (hssg:make-directory-artifact + (let ((artifact (hssg:make-directory-artifact pathname input-dir output-dir))) - (push artifact artifacts))))) + (hssg:compound-artifact-push static artifact)))) (defmethod push-post ((period hssg.blog.period:day-period) post) (with-slots ((posts hssg.blog.period:posts)) period diff --git a/src/hssg/artifacts/compound.lisp b/src/hssg/artifacts/compound.lisp index b89abb9..e16fc68 100644 --- a/src/hssg/artifacts/compound.lisp +++ b/src/hssg/artifacts/compound.lisp @@ -17,10 +17,22 @@ ;;;; ;;;; You should have received a copy of the GNU Affero General Public License ;;;; along with CL-HSSG If not, see .(in-package #:hssg.artifact) -(in-package #:hssg.artifact) +(in-package #:hssg.artifact._compound) -(defmethod write-artifact ((wrapper compound-artifact)) +(defmethod hssg.artifact:write-artifact ((wrapper hssg.artifact:compound-artifact)) "Writes each of the artifacts inside the WRAPPER individually." - (with-slots ((artifacts hssg.artifact::artifacts)) wrapper - (dolist (artifact artifacts) - (write-artifact artifact)))) + (dolist (artifact (slot-value wrapper 'hssg.artifact:artifacts)) + (hssg.artifact:write-artifact artifact))) + +(defun make-compound-artifact (&rest artifacts) + "Create a new compound artifact, which is a wrapper around the given + ARTIFACTS. Writing a compound artifact writes all the wrapped artifact in the + same order that was given as argument." + (make-instance 'hssg.artifact:compound-artifact :artifacts artifacts)) + +(defun compound-artifact-push (compound artifact) + "Push ARTIFACT to the beginning of the list or artifacts of the COMPOUND + artifact. This mutates COMPOUND in-place." + (with-slots ((artifacts hssg.artifact:artifacts)) + compound + (push artifact artifacts))) diff --git a/src/hssg/package.lisp b/src/hssg/package.lisp index 367e263..b921ef2 100644 --- a/src/hssg/package.lisp +++ b/src/hssg/package.lisp @@ -27,7 +27,18 @@ (:documentation "Helper package, defines the artifact protocl.") (:use #:cl) (:export write-artifact artifacts - verbatim-artifact compound-artifact directory-artifact html-artifact xml-artifact)) + compound-artifact verbatim-artifact directory-artifact html-artifact xml-artifact)) + +;;; --------------------------------------------------------------------------- +(defpackage #:hssg.artifact._compound + (:documentation "Implementatio of compound HSSG artifacts.") + (:use :cl) + (:export make-compound-artifact compound-artifact-push)) + +(defpackage #:hssg.artifact.directory + (:documentation "Helper package, contains verbatim artifacts") + (:use #:cl) + (:export make-directory-artifact)) (defpackage #:hssg.artifact.html (:documentation "Implementaion of HTML artifacts.") @@ -44,11 +55,6 @@ (:use #:cl) (:export make-verbatim-artifact)) -(defpackage #:hssg.artifact.directory - (:documentation "Helper package, contains verbatim artifacts") - (:use #:cl) - (:export make-directory-artifact)) - (defpackage #:hssg.template (:documentation "HTML template macros; templates transform SHTML aslists.") (:use #:cl) @@ -58,15 +64,20 @@ (defpackage #:hssg (:documentation "The hackable static site generator") (:use #:cl) - (:import-from #:hssg.artifact write-artifact compound-artifact artifacts html-artifact xml-artifact ) - (:import-from #:hssg.artifact.verbatim make-verbatim-artifact) + (:import-from #:hssg.artifact write-artifact artifacts html-artifact xml-artifact ) + (:import-from #:hssg.artifact._compound make-compound-artifact compound-artifact-push) (:import-from #:hssg.artifact.directory make-directory-artifact) + (:import-from #:hssg.artifact.verbatim make-verbatim-artifact) (:import-from #:hssg.artifact.html static-page read-html-lisp) (:import-from #:hssg.template deftemplate template let-metadata apply-template identity-template chain-templates template-with-data) (:export *site-url* *site-language* - write-artifact compound-artifact artifacts + ;; Artifact protocol + write-artifact + ;; Compound artifacts + make-compound-artifact compound-artifact-push + html-artifact xml-artifact static-page read-html-lisp make-verbatim-artifact make-directory-artifact deftemplate template let-metadata apply-template identity-template chain-templates template-with-data)) diff --git a/test/hssg/artifacts/compound.lisp b/test/hssg/artifacts/compound.lisp new file mode 100644 index 0000000..17e0aba --- /dev/null +++ b/test/hssg/artifacts/compound.lisp @@ -0,0 +1,46 @@ +(defpackage #:hssg/test/artifact/compound + (:use #:cl)) +(in-package #:hssg/test/artifact/compound) + +(fiveam:def-suite hssg/artifact/compound + :description "Compound artifact implementation tests") +(fiveam:in-suite hssg/artifact/compound) + + +;;; --------------------------------------------------------------------------- +(defstruct counter + "A mutable counter to keep track of how often the dummy artifact has been + written." + (count 0)) + +(defclass dummy-artifact () + ((counter :initarg :counter :accessor dummy-counter + :documentation "A (possibly shared) counter instance")) + (:documentation "A fake artifact which increments its counter")) + +(defmethod hssg:write-artifact ((dummy dummy-artifact)) + (incf (counter-count (dummy-counter dummy))) + :ok) + + +;;; --------------------------------------------------------------------------- +(fiveam:test create-and-write + "Writing a compound artifacts writes all all of its artifacts" + (let ((counter (make-counter))) + (let ((artifact (hssg:make-compound-artifact + (make-instance 'dummy-artifact :counter counter) + (make-instance 'dummy-artifact :counter counter) + (make-instance 'dummy-artifact :counter counter)))) + (hssg:write-artifact artifact)) + (fiveam:is (= 3 (counter-count counter))))) + +(fiveam:test push-artifact + "Push a new artifact onto the list of wrapped artifacts" + (let ((counter (make-counter))) + (let ((compound (hssg:make-compound-artifact)) + (dummy1 (make-instance 'dummy-artifact :counter counter)) + (dummy2 (make-instance 'dummy-artifact :counter counter))) + (hssg:compound-artifact-push compound dummy1) + (hssg:compound-artifact-push compound dummy2) + (hssg:write-artifact compound)) + (fiveam:is (= 2 (counter-count counter)))))