- Add RSS generation - Code enhancement - Escaping ~ which were problematic - cl-yag - Common Lisp Yet Another website Generator
HTML git clone git://bitreich.org/cl-yag/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/cl-yag/
DIR Log
DIR Files
DIR Refs
DIR Tags
DIR README
DIR LICENSE
---
DIR commit a6f07ecaad846e608500efa5cb5b3913a43db7e0
DIR parent e0a4614444c18e9840e4fa30d832da9fafedfa5e
HTML Author: Solene Rapenne <solene@dataswamp.org>
Date: Sun, 1 May 2016 00:43:31 +0200
- Add RSS generation
- Code enhancement
- Escaping ~ which were problematic
Diffstat:
M README.md | 8 ++++++--
M data/articles.lisp | 11 ++++++++++-
M generator.lisp | 80 ++++++++++++++++++++++---------
A template/rss-item.tpl | 5 +++++
A template/rss.tpl | 10 ++++++++++
5 files changed, 88 insertions(+), 26 deletions(-)
---
DIR diff --git a/README.md b/README.md
@@ -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.
DIR diff --git a/data/articles.lisp b/data/articles.lisp
@@ -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")
))
DIR diff --git a/generator.lisp b/generator.lisp
@@ -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)
DIR diff --git a/template/rss-item.tpl b/template/rss-item.tpl
@@ -0,0 +1,5 @@
+<item>
+ <title>%%Title%%</title>
+ <description>%%Description%%</description>
+ <link>%%Url%%</link>
+</item>
DIR diff --git a/template/rss.tpl b/template/rss.tpl
@@ -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>