Recently Written · git

cl-yag

Mirror and rewrite of Solène Rapenne's cl-yag SSG of renown

git clone https://github.com/equwal/cl-yag

Log | Files | Refs


generators/html.lisp (5771 bytes)

1 
2 (in-package #:cl-yag)
3 
4 (defun generate-rss-html(article)
5   (format nil "~d~d-~d.html"
6           (getf *config* :url)
7           (date-format "%Year-%MonthNumber-%DayNumber"
8                        (article-date article))
9           (article-id article)))
10 
11 (defun use-converter-to-html(filename &optional (converter-name nil))
12   "Generate HTML file from source file using the converter associated with the post."
13   (let* ((converter-object (getf *converters*
14                                  (or converter-name
15 			             (getf *config* :default-converter))))
16          (output           (converter-command converter-object))
17          (src-file (format nil "~a~a" filename (converter-extension converter-object)))
18          (dst-file (format nil "temp/data/~a.html" filename ))
19          (full-src-file (format nil "data/~a" src-file)))
20       ;; skip generating if the destination exists
21       ;; and is more recent than source
22       (unless (and
23                (probe-file dst-file)
24                (>=
25                 (file-write-date dst-file)
26                 (file-write-date full-src-file)))
27         (ensure-directories-exist "temp/data/")
28         (template "%IN" src-file)
29         (template "%OUT" dst-file)
30         (format t "~a~%" output)
31         (uiop:run-program output))))
32 
33 ;; We do all the website
34 (defun create-html-site()
35 
36   ;; produce each article file
37   (loop for article in *articles*
38      do
39      ;; use the article's converter to get html code of it
40        (use-converter-to-html (article-id article) (article-converter article))
41 
42 	(generate  (format nil "output/html/~d-~d.html"
43 			   (date-format "%Year-%MonthNumber-%DayNumber"
44 					(article-date article))
45 			   (article-id article))
46 		   (create-article article :tiny nil)
47 		   :title (concatenate 'string (getf *config* :title) " : " (article-title article))))
48 
49   ;; produce index.html
50   (generate "output/html/index.html" (generate-semi-mainpage))
51 
52   ;; produce index-titles.html where there are only articles titles
53   (generate "output/html/index-titles.html" (generate-semi-mainpage :no-text t))
54 
55   ;; produce index file for each tag
56   (loop for tag in (articles-by-tag) do
57        (generate (format nil "output/html/tag-~d.html" (getf tag :NAME))
58 		  (generate-tag-mainpage (getf tag :VALUE))))
59 
60   ;; generate rss gopher in html folder if gopher is t
61   (when (getf *config* :gopher)
62     (save-file "output/html/rss-gopher.xml" (generate-rss #'generate-rss-gopher)))
63 
64   ;;(generate-file-rss)
65   (save-file "output/html/rss.xml" (generate-rss #'generate-rss-html)))
66 
67 ;; html generation of index homepage
68 (defun generate-semi-mainpage(&key (tiny t) (no-text nil))
69   (apply #'concatenate 'string
70          (loop for article in *articles* collect
71               (create-article article :tiny tiny :no-text no-text))))
72 ;; html generation of a tag homepage
73 (defun generate-tag-mainpage(articles-in-tag)
74   (apply #'concatenate 'string
75          (loop for article in *articles*
76             when (member (article-id article) articles-in-tag :test #'equal)
77             collect (create-article article :tiny t))))
78 
79 ;; return a html string
80 ;; produce the code of a whole page with title+layout with the parameter as the content
81 (defun generate-layout(body &optional &key (title nil))
82   (prepare "templates/layout.tpl"
83 	   (template "%%Title%%" (if title title (getf *config* :title)))
84 	   (template "%%Tags%%" (get-tag-list))
85 	   (template "%%Body%%" body)
86 	   output))
87 
88 ;; generates the html of only one article
89 ;; this is called in a loop to produce the homepage
90 (defun create-article(article &optional &key (tiny t) (no-text nil))
91   (prepare "templates/article.tpl"
92 	   (template "%%Author%%" (let ((author (article-author article)))
93                                     (or author (getf *config* :webmaster))))
94 	   (template "%%Date%%"   (date-format (getf *config* :date-format)
95 					       (article-date article)))
96            (template "%%Raw-Date%%" (article-rawdate article))
97            (template "%%Title%%"  (article-title article))
98            (template "%%Id%%"     (article-id article))
99 	   (template "%%Tags%%"   (get-tag-list-article article))
100 	   (template "%%Date-Url%%"  (date-format "%Year-%MonthNumber-%DayNumber"
101 						  (article-date article)))
102 	   (template "%%Text%%"   (if no-text
103 				      ""
104                                       (if (and tiny (article-tiny article))
105                                           (format nil "<p>~a</p>" (article-tiny article))
106                                           (load-file (format nil "temp/data/~d.html" (article-id article))))))))
107 
108 ;; generates the html of the whole list of tags
109 (defun get-tag-list()
110   (apply #'concatenate 'string
111          (mapcar #'(lambda (item)
112                      (prepare "templates/one-tag.tpl"
113                               (template "%%Name%%" (getf item :name))))
114                  (articles-by-tag))))
115 
116 ;; generates the html of the list of tags for an article
117 (defun get-tag-list-article(&optional article)
118   (apply #'concatenate 'string
119          (mapcar #'(lambda (item)
120                      (prepare "templates/one-tag.tpl" (template "%%Name%%" item)))
121                  (split-str (article-tag article)))))
122 
123 ;; generate the list of tags
124 (defun articles-by-tag()
125   (let ((tag-list))
126     (loop for article in *articles* do
127 	  (when (article-tag article) ;; we don't want an error if no tag
128 	    (loop for tag in (split-str (article-tag article)) do ;; for each word in tag keyword
129 		  (setf (getf tag-list (intern tag "KEYWORD")) ;; we create the keyword is inexistent and add ID to :value
130 			(list
131 			 :name tag
132 			 :value (push (article-id article) (getf (getf tag-list (intern tag "KEYWORD")) :value)))))))
133     (loop for i from 1 to (length tag-list) by 2 collect ;; removing the keywords
134 	  (nth i tag-list))))
135 
136 
137