;;; build-lima.el --- Lima publishing adapter -*- lexical-binding: t; -*- ;;; Code: (require 'org) (require 'ox-publish) (defun z/lima-entry-title (file fallback) "Return FILE's Org title, or FALLBACK when no title is present." (with-temp-buffer (insert-file-contents file nil 0 4096) (goto-char (point-min)) (if (re-search-forward "^#\\+TITLE:[ \t]*\\(.+?\\)[ \t]*$" nil t) (match-string 1) fallback))) (defun z/lima-sitemap-format-entry (entry _style project) "Format a sitemap ENTRY for Lima; skip directories." (let* ((file (if (listp entry) (car entry) entry)) (base-dir (file-name-as-directory (org-publish-property :base-directory project))) (abs (if (file-name-absolute-p file) file (expand-file-name file base-dir)))) (unless (file-directory-p abs) (let* ((rel (file-relative-name abs base-dir)) (rel-noext (file-name-sans-extension rel)) (title (z/lima-entry-title abs (file-name-nondirectory rel-noext)))) (format "[[file:%s.html][%s]]" rel-noext title))))) (defun z/copy-neighbor-attachments (source-dir pub-dir) "Copy sibling .attachments.* directories from SOURCE-DIR into PUB-DIR." (dolist (d (directory-files source-dir t "^\\.attachments\\..+")) (when (file-directory-p d) (let ((target (expand-file-name (file-name-nondirectory d) pub-dir))) (make-directory target t) (copy-directory d target t t t))))) (defun z/markdown-h1-title (filename fallback) "Return the first Markdown H1 title in FILENAME, or FALLBACK." (with-temp-buffer (insert-file-contents filename nil 0 4096) (goto-char (point-min)) (if (re-search-forward "^#+ +\\(.+?\\)\\s-*$" nil t) (match-string 1) fallback))) (defun z/publish-lima-file (plist filename pub-dir) "Publish an Org or Markdown file from the lima directory." (let* ((ext (downcase (or (file-name-extension filename) ""))) (base (file-name-base filename)) (src-dir (file-name-directory filename))) (cond ((string= ext "org") (z/copy-neighbor-attachments src-dir pub-dir) (org-publish-org-to 'z-html filename ".html" plist pub-dir)) ((string= ext "md") (let* ((tmp-dir (make-temp-file "lima-build-" t)) (temp-org (expand-file-name (concat base ".org") tmp-dir))) (let ((rc (call-process "pandoc" nil nil nil filename "-f" "markdown" "-t" "org" "-o" temp-org))) (unless (zerop rc) (z/log 'error "pandoc failed (rc=%d) for %s" rc filename) (error "pandoc conversion failed for %s" filename))) (with-temp-buffer (insert-file-contents temp-org) (goto-char (point-min)) (insert (format "#+TITLE: %s\n#+OPTIONS: num:nil\n#+DATE: %s\n#+COMMENTS: t\n#+SLUG: %s\n\n" (z/markdown-h1-title filename base) (format-time-string "<%Y-%m-%d %a %H:%M>") base)) (write-region (point-min) (point-max) temp-org)) (z/copy-neighbor-attachments src-dir pub-dir) (let ((output-file (expand-file-name (concat base ".html") pub-dir))) (org-publish-org-to 'z-html temp-org ".html" plist pub-dir) (let ((generated (expand-file-name (concat (file-name-base temp-org) ".html") pub-dir))) (when (and (file-exists-p generated) (not (string-equal generated output-file))) (rename-file generated output-file t)))))) (t (org-publish-attachment plist filename pub-dir))))) (provide 'build-lima) ;;; build-lima.el ends here