Org Mode Project Specification

Menu

Introduction

This page contains the specification to build this website using Org Mode.

You might want to look and set some of the variables in the Project Specification section.

This file can be found here:

/home/adolfo/Sites/home/project-specification

To load this configuration, either M-x org-babel-execute-buffer this buffer or put in your Emacs initialization file (.emacs.el):

(setq project-location (expand-file-name "~/Sites/home/project-specification/project-specification.org"))

(if (file-exists-p project-location)
    (org-babel-load-file project-location)
  (message "Warning! project specification (%s) not found (check init.el)" project-location))

Static website functions

We use the functions defined in

(setq load-path (append load-path '(".")))
(require 'website-management nil t)
(require 'website-metadata nil t)

Project Specification

The project name is:

(setq name "home")

On which port do we run it when previewing locally?

(setq preview-port 4700)

Where are the sources, where do we save resulting HTML files and from which directory do we start serving local preview? (Notice that flexibility between local-dest and preview-dir allows to run a local server on a suburi.)

(setq sources (expand-file-name "~/Sites/home/"))
(setq local-dest (concat (file-name-as-directory sources) "_site/adolfo"))
(setq preview-dir (concat (file-name-as-directory sources) "_site/"))

Where do we deploy the generated HTML?

Set to nil if no remote deployment is necessary, in which case the website will be available in the local-dest directory:

(setq deploy-dest "adolfo@home:/srv/http/ict4g_net/adolfo")

The project will be structured in two components, content and assets:

(setq content (concat name "-content"))
(setq assets (concat name "-assets"))

This is a custom publishing function to choose the Reveal engine for files whose name ends with -reveal (before the extension). it replaces org-html-publish-to-html as the “:publishing-function”

(defun avm/org-publish-html-or-reveal (plist filename pub-dir)
  "Publish using the standard HTML or Reveal engine, if filename ends with -reveal."
  (if (string-match "-reveal\\.org$" filename)
      (org-reveal-export-to-html)
    (org-html-publish-to-html plist filename pub-dir)))

;; this is pure magic to avoid an issue with client-multiplex
;; undefined when publishing with reveal
;; (setq client-multiplex nil)

(setq project-specification
      `((,name
         :components (,content ,assets)
         :local-dir ,local-dest
         :preview-dir ,preview-dir
         :deploy-dir ,deploy-dest
         :port ,preview-port
         )

        (,content
         :base-directory ,sources
         :publishing-directory ,local-dest
         :publishing-function (avm/org-publish-html-or-reveal org-org-publish-to-org)
         ;; :publishing-function (org-html-publish-to-html org-org-publish-to-org)
         :base-extension "org"
         :exclude "\\(\\.git\\|_site\\|^_\\.*\\|.*~\\)"
         :recursive t

         :html-doctype "html5"
         :htmlized-source t

         :section-numbers nil
         :with-toc nil
         :with-broken-links nil
         :html-head-include-default-style nil
         :html-head-include-scripts nil
         :html-postamble "
 <div class=\"footer-contacts\">
    <script language=\"javascript\">
      var n = \"adolfo\"
      var s = \"villafiorita\"
      var d = \"shair.tech\"
      var content = \"comment by e-mail\"
      document.write('<a href=\"mailto:' + n +'@' + d + '\">' + content + '</a>');   
     </script>
 </div>
 <div class=\"footer-metadata\">
   <p class=\"author\">Author: %a</p>
   <p class=\"date\">Published: %T</p>
   <p class=\"date\">Last modified: %C</p>
   <p class=\"date\">Created: %d</p>
   <p id=\"source-link\" class=\"source\"></p>
 </div>"
         )

        (,assets
         :base-directory ,sources
         :publishing-directory ,local-dest
         :publishing-function org-publish-attachment
         :base-extension "atom\\|css\\|js\\|gif\\|jpg\\|png\\|svg\\|webm\\|pdf\\|txt\\|csv\\|tsv\\|xml\\|ttf\\|woff\\|gz\\|vcf"
         :exclude "\\(.git\\|_site\\|^_.*\\|.*~\\)"
         :recursive t
         )

         ))

Remove the project specification, if already present, so that we can modify and re-evaluate this page:

(let ( (components (mapcar (lambda (x) (car x)) project-specification)) )
   (mapcar 
      (lambda (x)
        (setq org-publish-project-alist
              (assoc-delete-all x org-publish-project-alist)))
      components))

Add the project specification to the list of Org Mode projects:

(setq org-publish-project-alist (append project-specification org-publish-project-alist))

Building, Previewing, Deploying

Once you have everything in place, you can use the following functions (the first is syntactic sugar for org-publish).

  • M-x website-build-project
  • M-x website-preview-project
  • M-x website-deploy-project

Generating Dynamic content

The functions in website-metadata read the metadata of all files of a project and provide facilities for generating “dynamic” content, such as, for instance, the list of posts. This is achieved using source code blocks in pages.

For instance, this snippet generates a list of posts in chronological order:

#+BEGIN_SRC emacs-lisp :exports results :results output html :dir .
  (org-babel-load-file "../project-specification/website-metadata.org")

  ;; get metadata of all the files from here
  (setq metadata (files-metadata "."))
  ;; remove files in this directory (which are index files)
  (setq metadata (seq-filter (lambda (x) (< 2 (length (split-string (cdr (assoc "FILENAME" x)) "/")))) metadata))

  (princ
    (group-to-html
      (sort-group-by-year
        (group-by-year (sort-metadata metadata "DATE_ISO8601" 'string-greaterp))) t))
#+END_SRC