|
- :;exec cask emacs --no-site-file --no-site-lisp --batch -L ./ -l "$0" -f main "$(cd "$(dirname "$0")/." >/dev/null 2>&1 ; pwd -P)" "$@"
- ;;; build.el --- The build script of my personal website
- ;;; Version: 0.1.0
- ;;; Package-Version 0.1.0
- ;;; Commentary:
- ;;; Code:
- (require 'org)
- (require 'seq)
- (require 'ox-html)
- (require 'ox-latex)
- (require 'ox-publish)
- (require 'dracula-theme)
- (require 'lisp/ox-template)
- (require 'lisp/utils)
-
-
- (setq debug-on-error t)
-
- (defvar author-name "Sameer Rahmani"
- "Set this variable to your fullname.")
-
- (defvar author-email "lxsameer@gmail.com"
- "Set this varibale to your email address.")
-
- (defvar project-root nil
- "Root directory of the website source code.")
-
-
- (defvar orgs-files-dir "/orgs/"
- "Path to the directory containing all the renderable org files.")
-
-
- (defun from-root (path)
- "Return the full path of the given PATH in the project root."
- (concat project-root path))
-
-
- (defun all-org-files ()
- "Return a list of all the org files in the orgs directory."
- (mapcar (lambda (x) x)
- (split-string
- (shell-command-to-string (format "find %s -iname \"*.org\"" org-directory))
- "\n" t)))
-
- (comment
- (all-org-files))
-
-
- (defun get-all-tags ()
- "Return a list of all the tags in the org files."
- (seq-reduce
- ;; all-tags is in (tags . tags->files) form
- (lambda (all-tags file)
- (if (get-file-global-props file "PAGE")
- ;; Ignore pages
- all-tags
- (with-temp-buffer
- (insert-file-contents file)
- (let ((tags (mapcar #'car (org-get-buffer-tags))))
- (seq-reduce
- (lambda (result tag)
- (let ((tag-list (car result))
- (tag->file (cdr result)))
- (cons
- ;; Tag list
- (if (member tag tag-list) tag-list (sort (cons tag tag-list) 'string<))
- ;; tag->file
- (cons (cons tag
- ;; Current value of the the given tag (all the files
- ;; that contain that tag)
- (append (list file) (cdr (assoc tag tag->file))))
- tag->file))))
- tags
- all-tags)))))
- (all-org-files)
- '()))
-
-
- (defun get-all-posts ()
- "Return all the post org files.
- Not pages."
- (let ((files (all-org-files)))
- (seq-reduce
- (lambda (result file)
- (let ((is-page? (string= (get-file-global-props file "PAGE") "true")))
- (if (not is-page?)
- ;; It's a post
- (cons
- (list
- ;; This is not effecient since we parse the file
- ;; on each query, but who cares :D ?
- (->epoch (get-file-global-props file "DATE"))
- (get-file-global-props file "TITLE")
- (replace-regexp-in-string "\\.org" ".html"
- (file-name-nondirectory file)))
- result)
- result)))
- files
- '())))
-
-
- (defun get-all-sorted-posts ()
- "Return all posts in sorted order."
- (sort
- (get-all-posts)
- (lambda (x y) (> (car x) (car y)))))
-
-
- (comment
- (get-all-sorted-posts))
-
-
- (defun get-all-categories ()
- "Return all the categories of the org files."
- (seq-reduce
- ;; all-cats is in (cats . cat->files) form
- (lambda (all-cats file)
- (let ((is-page? (string= (get-file-global-props file "PAGE") "true"))
- (cat (get-file-global-props file "CATEGORY"))
- (cat-list (car all-cats))
- (cat->file (cdr all-cats)))
-
- (if (not is-page?)
- (cons
- ;; Category list
- (if (member cat cat-list) cat-list (sort (cons cat cat-list) 'string<))
- ;; cat->file
- (cons (cons cat
- ;; Current value of the the given cat (all the files
- ;; under that category)
- (append (list file) (cdr (assoc cat cat->file))))
- cat->file))
- all-cats)))
- (all-org-files)
- '()))
-
-
- (comment
- (get-file-global-props "./orgs/essays/serene-blah.org" "CATEGORY")
- (get-all-categories))
-
-
- (defun extra-headers ()
- "Retun a list of extra header html tags."
- (concat
- "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">"))
-
-
- (defun category-org-list ()
- "Return a list of links to the categories in org format."
- (let ((categories (get-all-categories)))
- (mapconcat
- (lambda (cat)
- (let ((count (length (cdr (assoc cat (cdr categories))))))
- (format " - [[./%s.html][%s(%s)]]" cat cat count)))
- (car categories)
- "\n")))
-
-
- (defun tags-org-list ()
- "Return a list of links to the tags in org format."
- (let ((tags (get-all-tags)))
- (mapconcat
- (lambda (tag)
- (let ((count (length (cdr (assoc tag (cdr tags))))))
- (format " - [[./%s.html][%s(%s)]]" tag tag count)))
- (car tags)
- "\n")))
-
-
- (defun latest-org-list (base-url)
- "Return a list of links (using BASE-URL) to the tags in org format."
- (let ((posts (get-all-sorted-posts)))
- (mapconcat
- (lambda (post)
- (format " - [[%s/essays/%s][%s]]" base-url (nth 2 post) (nth 1 post)))
- posts
- "\n")))
-
-
- (comment
- (latest-org-list))
-
-
- (defun pair-file-with-date (file)
- "Return a pair for the given FILE with date as car and file as cdr."
- (cons
- (->epoch (get-file-global-props file "DATE"))
- file))
-
-
- (defun create-tag-pages (project-dir)
- "Create all the tag files in the PROJECT-DIR."
- (let ((tags (get-all-tags)))
- (mapcar
- (lambda (tag)
- (let ((out (format "%s/orgs/tags/%s.org" project-dir tag))
- (files (cdr (assoc tag (cdr tags)))))
- (copy-template
- (format "%s/templates/links_template.org" project-dir)
- out
- (mapconcat
- (lambda (file-pair)
- (format "- [[file:..%s][%s]]"
- (replace-regexp-in-string (regexp-quote (from-root "/orgs")) "" (cdr file-pair) nil 'literal)
- (get-file-global-props (cdr file-pair) "TITLE")))
-
- (sort
- (mapcar #'pair-file-with-date files)
- (lambda (x y) (> (car x) (car y))))
- "\n")
- tag)))
- (car tags))))
-
-
- (defun create-category-pages (project-dir)
- "Create all the category files in the PROJECT-DIR."
- (let ((tags (get-all-categories)))
- (mapcar
- (lambda (tag)
- (let ((out (format "%s/orgs/categories/%s.org" project-dir tag))
- (files (cdr (assoc tag (cdr tags)))))
- (copy-template
- (format "%s/templates/links_template.org" project-dir)
- out
- (mapconcat
- (lambda (file-pair)
- (format "- [[file:..%s][%s]]"
- (replace-regexp-in-string (regexp-quote (from-root "/orgs")) "" (cdr file-pair) nil 'literal)
- (get-file-global-props (cdr file-pair) "TITLE")))
-
- (sort
- (mapcar #'pair-file-with-date files)
- (lambda (x y) (> (car x) (car y))))
- "\n")
- tag)))
- (car tags))))
-
-
- (defun main ()
- "The entry point to the build script."
-
- ;; Setup the emacs theme so htmlize can actually setup
- ;; the code highlighter
- (load-theme 'dracula t)
- (enable-theme 'dracula)
-
-
- (setq project-root (car command-line-args-left))
-
- ;; We will use the org-agenda to extract all the tags
- (setq org-directory (from-root orgs-files-dir))
- (setq org-agenda-files (all-org-files))
-
- (setf user-full-name author-name)
- (setf user-mail-address author-email)
-
- ;; Disable default header links (top, next)
- (setf org-html-home/up-format "")
- (setf org-html-link-up "")
- (setf org-html-link-home "")
- (setf org-html-scripts "")
-
- ;; (org-babel-do-load-languages
- ;; 'org-babel-load-languages
- ;; '(
- ;; (emacs-lisp . t)
- ;; (org . t)
- ;; (shell . t)
- ;; (C . t)
- ;; (python . t)
- ;; (clojure .t)
- ;; (lisp . t)
- ;; (js . t)
- ;; (awk . t)))
-
- ;; ;; Never export the code block evaluation
- ;; (setq org-babel-default-header-args '((:eval . "never-export")))
- ;; (setq org-src-fontify-natively t)
-
- (let ((build-dir (from-root "/build/"))
- (base-url (if (prod-p) "https://lxsameer.com" "http://localhost:3003")))
- (copy-template (from-root "/templates/index.org")
- (from-root "/orgs/index.org")
- (latest-org-list base-url))
-
- (copy-template (from-root "/templates/categories.org")
- (from-root "/orgs/categories/index.org")
- (category-org-list))
-
- (copy-template (from-root "/templates/tags.org")
- (from-root "/orgs/tags/index.org")
- (tags-org-list))
-
- (create-tag-pages project-root)
- (create-category-pages project-root)
-
- (setq org-html-preamble #'preamble-fn)
- (setq org-html-htmlize-output-type nil)
- (setq org-latex-listings t)
-
- (setq org-publish-project-alist
- `(("lxsameer.com"
- :base-directory ,(from-root "/orgs")
- :root-directory ,project-root
- :recursive t
- :base-extension "org"
- :publishing-directory ,build-dir
- ;; Exclude the blog archive index autogenerated below
- ;; Note that the regexp is relative to :base-directory
- ;; :exclude "^index.org"
- :section-numbers nil
- :with-author t
- :with-drawers t
- :html-format-drawer-function custom-drawer-format
- :with-properties t
- :with-tags t
- :with-timestamps t
- :with-toc nil
- :base-url ,base-url
- :html-link-home "/"
- :html-head-extra ,(extra-headers)
- :html-template ,(from-root "/templates/blog.html")
- :html-page-preamble-template ,(from-root "/templates/page-preamble.html")
- :html-post-preabmle-template ,(from-root "/templates/post-preamble.html")
- :html-tags-template ,(from-root "/templates/tags.html")
- :publishing-function org-html-publish-to-templated-html
- :auto-sitemap t
- :htmlized-source nil
- :sitemap-folders ignore
- :sitemap-style list
- :sitemap-title "lxsameer's nest"
- :sitemap-filename "sitemap.inc"
- :sitemap-sort-files anti-chronologically
- :html-format-headline-function headline-format
- :makeindex nil)
-
- ("org->html"
- :base-directory ,(from-root "/orgs")
- :base-extension "org"
- :publishing-directory ,build-dir
- :recursive t
- :publishing-function org-html-publish-to-html
- :headline-levels 4
- ;; :html-preamble ,(use-html "templates/header.html")
- ;; :html-postamble ,(use-html "templates/footer.html")
- :html-link-home "/"
- :html-head-include-default-style nil
- :html-head-include-scripts nil
- :html-head-extra ,(extra-headers)
- :makeindex nil)
-
- ("pdfs"
- :base-directory ,(from-root "/orgs/essays")
- :root-directory ,project-root
- ;;:publishing-directory ,(concat build-dir "/essays/")
- :recursive t
- :base-extension "org"
- :publishing-directory ,build-dir
- :publishing-function org-latex-publish-to-pdf)
-
-
- ("statics"
- :base-directory ,project-root
- :base-extension "css\\|js\\|png\\|jpg\\|gif\\|pdf\\|svg"
- :publishing-directory ,build-dir
- :recursive t
- :publishing-function org-publish-attachment)
- ("build" :components ("lxsameer.com" "statics"))))
-
- (org-publish-project "build" t nil)
- (message "Build complete.")))
-
-
- (provide 'build)
- ;; Local Variables:
- ;; mode: emacs-lisp
- ;; End:
- ;;; build.el ends here
|