- Add RSS generation

- Code enhancement
- Escaping ~ which were problematic
This commit is contained in:
Solene Rapenne 2016-05-01 00:43:31 +02:00
parent e0a4614444
commit a6f07ecaad
5 changed files with 88 additions and 26 deletions

View File

@ -39,7 +39,7 @@ I tried to make it "hacking friendly" so it's very extensible.
Here is an example code if you want to add something like a panel on the layout.
+ Add a string for the replacement to occure, like %%Panel%% in **template/layout.tpl** (because we want the panel on every page)
+ In **generator.lisp** modify the function *generate-layout* to add "**(template "%%Panel%%" (slurp-file "template/panel.tpl"))**" after one template function call
+ In **generator.lisp** modify the function *generate-layout* to add "**(template "%%Panel%%" (load-file "template/panel.tpl"))**" after one template function call
+ Create **template/panel.tpl** with the html
(note : you can also directly add your text inside the layout template file instead of including another file)
@ -50,7 +50,7 @@ You may want to have some dedicated page for some reason, reusing the website la
In **generate-site** function we can load a file, apply the template and save it in the output. It may look like this
(generate "somepage.html" (slurp-file "data/mypage.html"))
(generate "somepage.html" (load-file "data/mypage.html"))
This will produce the file somepage.html in the output folder
@ -66,3 +66,7 @@ Here is a tip to produce html files from markdown using emacs
4. run *make* to update your site
The generator don't do it natively because I didn't want it to have dependencies. You can use what you want to produces the html files.
# Known limitation
The application will crash if you use a single "**~**" caracter inside one data structure in **articles.lisp** files. This is due to the format function trying to interpret the ~ symbol while we just one a ~ symbol. This symbol in the others files are automatically replaced by ~~ which produce a single ~. So, if you want to have a "~" as a title/url/author/description/short/date you have to double it. It may be interestind to sanitize it in the tool maybe.

View File

@ -1,15 +1,24 @@
;; WARNING caracter "~" must be escaped when used in this file
;; you have to type ~~ for one ~ to escape it
;; define informations about your blog
;; used for the RSS generation and some variables replacements in the layout
(defvar *config*
(list
:webmaster "Your author name here"
:title "Your blog title here"
:description "Yet another website on the net"
:url "https://my.website/~~user/"
))
;; describes articles (ordered)
;; describes articles (ordered on the website as they are displayed here, the first in list is the top of the website)
;; exemple => (list :id "4" :date "2015-05-04" :title "The article title" :author "Me" :tiny "Short description for home page")
;; :author can be omitted and will be replaced by webmaster value
;; :tiny can be omitted and will be replaced by the full article text
(defvar *articles*
(list
(list :id "2" :date "30 April 2016" :title "Another message" :short "New version available")
(list :id "1" :date "29 April 2016" :title "My first message" :short "This is my first message" :author "Solène")
))

View File

@ -13,12 +13,16 @@
:end (or pos (length string)))
when pos do (write-string replacement out)
while pos)))
;; load a file and return it as a string
(defun slurp-file(path)
(with-open-file (stream path)
(let ((data (make-string (file-length stream))))
(read-sequence data stream)
data)))
;; load a file as a string
;; we escape ~ to avoid failures with format
(defun load-file(path)
(replace-all
(with-open-file (stream path)
(let ((data (make-string (file-length stream))))
(read-sequence data stream)
data))
"~" "~~"))
;; save a string in a file
(defun save-file(path data)
@ -33,54 +37,84 @@
;; simplify the declaration of a new page type
(defmacro prepare(template &body code)
`(progn
(let ((output (slurp-file ,template)))
(let ((output (load-file ,template)))
,@code
output)))
;; simplify the file saving by using the layout
(defmacro generate(name &body data)
`(progn
(save-file ,name
(generate-layout ,@data))))
;; generates the html of one only article
;; this is called in a loop to produce the homepage
(defun create-article(article &optional &key (tiny t))
(prepare "template/article.tpl"
(template "%%Author%%" (if (member :author article) (getf article :author) (getf *config* :webmaster)))
(template "%%Author%%" (getf article :author (getf *config* :webmaster)))
(template "%%Date%%" (getf article :date))
(template "%%Title%%" (getf article :title))
(template "%%Id%%" (getf article :id))
(template "%%Text%%" (if (and tiny (member :tiny article))
(getf article :tiny) (slurp-file (format nil "data/~d.txt" (getf article :id)))))))
(getf article :tiny) (load-file (format nil "data/~d.txt" (getf article :id)))))))
;; return a html string
;; produce the code of a whole page with title+layout with the parameter as the content
(defun generate-layout(body)
(let ((output (slurp-file "template/layout.tpl")))
(template "%%Title%%" (getf *config* :title))
(template "%%Body%%" body)
output))
(prepare "template/layout.tpl"
(template "%%Title%%" (getf *config* :title))
(template "%%Body%%" body)
output))
;; Homepage generation
;; generate each article and concatenate the whole
(defun generate-mainpage()
(prepare "template/layout.tpl"
(template "%%Body%%"
(format nil "~{~d~}"
(loop for article in *articles* collect
(create-article article :tiny t))))
(template "%%Title%%" (getf *config* :title))))
;; Generate the items for the xml
(defun generate-rss-item()
(format nil "~{~d~}"
(loop for article in *articles* collect
(create-article article :tiny t))))
(prepare "template/rss-item.tpl"
(template "%%Title%%" (getf article :title))
(template "%%Description%%" (getf article :short ""))
(template "%%Url%%"
(format nil "~d/article-~d.html"
(getf *config* :url)
(getf article :id)))))))
;; Generate the rss xml data
(defun generate-rss()
(prepare "template/rss.tpl"
(template "%%Description%%" (getf *config* :description))
(template "%%Title%%" (getf *config* :title))
(template "%%Url%%" (getf *config* :url))
(template "%%Items%%" (generate-rss-item))))
;; ENGINE START !
;; This is function called when running the tool
(defun generate-site()
; produce index.html
(generate "index.html"
(generate-mainpage))
; produce each article file
;; produce index.html
(save-file "index.html"
(generate-mainpage))
;; produce each article file
(dolist (article *articles*)
(generate (format nil "article-~d.html" (getf article :id))
(create-article article :tiny nil)))
;;(generate-file-rss)
;;not done yet
(save-file "rss.xml"
(generate-rss))
)
(generate-site)

5
template/rss-item.tpl Normal file
View File

@ -0,0 +1,5 @@
<item>
<title>%%Title%%</title>
<description>%%Description%%</description>
<link>%%Url%%</link>
</item>

10
template/rss.tpl Normal file
View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
<channel>
<title>%%Title%%</title>
<description>%%Description%%</description>
<link>%%Url%%</link>
%%Items%%
</channel>
</rss>