- Add RSS generation - Code enhancement - Escaping ~ which were problematic - cl-yag - Common Lisp Yet Another website Generator
 (HTM) 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
 (HTM) 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>