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