This repository contains code that generates my personal website, https://asilata.github.io/.
The content for the website goes in the content/
directory.
It is written as a collection of inter-linked org files.
An internal directory structure is supported.
We begin by creating an elisp file to build the webpage, as explained in this post.
I will tangle the following snippets of elisp code to a file called build.el
.
Initialise some libraries. Use ox-publish to publish the website. The github container’s emacs (and therefore org) version is old, so I am installing a newer one from a ppa. I will probably eventually run this in a docker emacs container, as described here.
(message (emacs-version))
(require 'ox-publish)
(require 'subr-x)
First, locally define some html and tex variables to prepare for publishing.
(let ((ab/html-head "<link rel=\"stylesheet\" href=\"css/stylesheet.css\">")
(ab/html-head-extra
(string-join
'("<link href=\"https://fonts.googleapis.com/css?family=Neuton:400,400i,700,700i\" rel=\"stylesheet\">")))
(ab/html-postamble
"<footer>
Page generated using %c. Last modified on %C. Source on <a href=\"https://github.com/asilata/asilata.github.io\">github</a>.
</footer>")
(ab/latex-classes
'(("moderncv"
"\\documentclass[a4paper]{moderncv}
[NO-DEFAULT-PACKAGES]
\\usepackage{amsmath,amssymb}"
("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\paragraph{%s}" . "\\paragraph*{%s}")
("\\subparagraph{%s}" . "\\subparagraph*{%s}"))))
)
Next set the options for org-publish-project-alist
, as documented here.
Currently I have the following projects.
- The first one, called
website
, contains all the content generated from org-mode files. - The second one, called
assets
, copies over all the files in the assets directory. - The third one, called
css
, copies over the css files from the css directory. - The fourth one, called
cv
, automatically builds the cv from the data file.
The various publishing options are documented here.
(setq org-publish-project-alist
`(("website"
:base-directory "./content"
:publishing-directory "./public"
:recursive t
:exclude "data\\|cv\\|stylesheet"
:publishing-function org-html-publish-to-html
:with-broken-links t
:with-creator t
:with-title nil
:with-toc nil
:html-head-include-default-style nil
:html-head-include-scripts nil
:html-head ,ab/html-head
:html-head-extra ,ab/html-head-extra
:html-postamble ,ab/html-postamble
:html-preamble ab/make-html-preamble
:section-numbers nil
)
("assets"
:base-directory "./content/assets"
:base-extension "jpg\\|pdf"
:publishing-directory "./public/assets"
:recursive t
:publishing-function org-publish-attachment)
("css"
:base-directory "./content/css"
:base-extension "css"
:publishing-directory "./public/css"
:recursive t
:publishing-function org-publish-attachment)
("cv-pdf"
:base-directory "./content/cv"
:publishing-directory "./public/cv"
:latex-hyperref-template nil
:latex-classes ,ab/latex-classes
:publishing-function org-latex-publish-to-latex
)
("cv-html"
:base-directory "./content/cv"
:publishing-directory "./public"
:publishing-function org-html-publish-to-html
:with-broken-links t
:with-creator t
:with-title nil
:with-toc nil
:html-head-include-default-style nil
:html-head-include-scripts nil
:html-head ,ab/html-head
:html-head-extra ,ab/html-head-extra
:html-postamble ,ab/html-postamble
:html-preamble ab/make-html-preamble
:section-numbers nil
)
)
))
Note that the html preamble is set via a function, called ab/make-html-preamble
.
It is defined as follows.
(defun ab/make-html-preamble (options)
(concat "<header>"
"<h1><a href=\"/\">Asilata Bapat</a></h1>"
"<nav>"
(ab/make-navbar)
"</nav></header>"))
The above function calls ab/make-navbar
, which we define as follows.
(defun ab/make-navbar ()
(let ((lst '("Home" "Teaching" "Research" "Activities"))
(title (cadar (org-collect-keywords '("TITLE")))))
(concat "<ul>\n"
(string-join
(mapcar (lambda (x) (ab/make-nav-item x title)) lst) "\n")
"\n</ul>")))
In turn, the above function calls ab/make-nav-item
.
(defun ab/make-nav-item (str title)
(let ((slug (if (string-equal str "Home") "index" (downcase str))))
(format "<li><a href=\"%s.html\"%s>%s</a></li>"
slug
(if (string-equal str title) " class=\"active\"" "")
str)))
Now publish!
(setq org-confirm-babel-evaluate nil)
(setq make-backup-files nil)
(org-publish-all t)
(message "Build complete!")
We also create a shell script to run the above lisp file.
emacs --batch \
--eval "(setq org-confirm-babel-evaluate nil)" \
--eval "(let ((enable-local-variables :all)) (hack-local-variables))" \
-l build.el
Once we have set up the tools to build the website locally, we can now use them to build the site automatically on Github.
Put the following code in .github/workflows/build.yml
.
Inspired by this post and this post.
name: Build and publish to GitHub Pages
on:
push:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v2
- name: Install emacs
uses: purcell/setup-emacs@master
with:
version: 27.2
- name: Build website
run: ./build.sh
- name: Run latex
uses: xu-cheng/latex-action@v2
with:
work_in_root_file_dir: true
root_file: public/cv/cv.tex
- name: Publish to gh-pages branch
uses: JamesIves/github-pages-deploy-action@4.1.4
if: success()
with:
branch: gh-pages
folder: public