Blog Home
Updated: 2023 Oct 09

如何创建org-mode 博客

structure

├── makefile
├── org
│   ├── blog
│   │   └── org-mode-blog.org
│   ├── css
│   │   ├── modus-operandi.css
│   │   ├── modus-vivendi.css
│   │   └── style.css
│   └── index.org
└── publish.el

init.el

;; Snippets E.G. <E
;;a       ‘#+BEGIN_EXPORT ascii’ … ‘#+END_EXPORT’
;;c       ‘#+BEGIN_CENTER’ … ‘#+END_CENTER’
;;C       ‘#+BEGIN_COMMENT’ … ‘#+END_COMMENT’
;;e       ‘#+BEGIN_EXAMPLE’ … ‘#+END_EXAMPLE’
;;E       ‘#+BEGIN_EXPORT’ … ‘#+END_EXPORT’
;;h       ‘#+BEGIN_EXPORT html’ … ‘#+END_EXPORT’
;;l       ‘#+BEGIN_EXPORT latex’ … ‘#+END_EXPORT’
;;q       ‘#+BEGIN_QUOTE’ … ‘#+END_QUOTE’
;;s       ‘#+BEGIN_SRC’ … ‘#+END_SRC’
;;v       ‘#+BEGIN_VERSE’ … ‘#+END_VERSE’
(require 'org-tempo)

;; timestamp format
(setf org-html-metadata-timestamp-format "%Y %b %d")
(setf org-export-date-timestamp-format "%Y-%m-%d")

;; Truncate line e.g. M-x toggle-truncate-lines
(add-hook 'org-mode-hook (lambda () (setq truncate-lines nil)))

;; Enable HTML5
(setq org-html-html5-fancy t
      org-html-doctype     "html5")

;; Disable ox-html's default CSS and JavaScript
(setq org-html-head-include-default-style nil
      org-html-head-include-scripts       nil)

;; Don't show section numbers or table of contents by default
(setq org-export-with-section-numbers nil
      org-export-with-toc             nil)

;; TODO: tweak headline id format. I dislike the randomly generated ones.
;; Look into customizing: :html-format-headline-function and
;; org-html-format-headline-function
;; (setq org-html-self-link-headlines 'nil)

(require 'ox-html)
;; Render ~verbatim~ as kbd tag in HTML
(add-to-list 'org-html-text-markup-alist '(verbatim . "<kbd>%s</kbd>"))

;; Enable code syntax highlighting if available
(require 'package)
(add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/"))
(setq package-load-list '((htmlize t)))
(package-initialize)

(unless (package-installed-p 'htmlize)
  (package-refresh-contents)
  (package-install 'htmlize))

(if (package-installed-p 'htmlize)
    (setq org-html-htmlize-output-type 'css)
  (setq org-html-htmlize-output-type 'nil))

publish.el

(load "~/.emacs.d/init.el")
(require 'ox-publish)

(setq org-export-global-macros
      '(("timestamp" . "@@html:<span class=\"timestamp\">[$1]</span>@@")
	("cc-by-nd" . "@@html:<div class=\"license-notice-container\">
  <div class=\"license-notice\">
    <div class\"notice\">
      <span><b>Note:</b></span>
      <span>
        <a rel=\"license\" href=\"http://creativecommons.org/licenses/by-nd/4.0/\">
          <img alt=\"Creative Commons License\"
               src=\"https://i.creativecommons.org/l/by-nd/4.0/88x31.png\" />
        </a>
      </span>
    </div>
    This post is licensed under the
    <a rel=\"license\" href=\"http://creativecommons.org/licenses/by-nd/4.0/\">
      CC-BY-ND 4.0
    </a>.
  </div>
</div>@@")
	("right-justify" . "@@html:<span class=\"right-justify\">$1</span>@@")))

(defun org-sitemap-custom-entry-format (entry style project)
  "Sitemap PROJECT ENTRY STYLE format that includes date."
  (let ((filename (org-publish-find-title entry project)))
    (if (= (length filename) 0)
        (format "*%s*" entry)
      (format "{{{timestamp(%s)}}} [[file:%s][%s]]"
              (format-time-string "%Y-%m-%d"
				  (org-publish-find-date entry project))
              entry
              filename))))

(defvar blog-css "<link rel=\"stylesheet\" href=\"/css/style.css\" type=\"text/css\"/>")
(defvar blog-css-extra "<link rel=\"stylesheet\" media=\"(prefers-color-scheme: light)\" href=\"/css/modus-operandi.css\" type=\"text/css\"/>
<link rel=\"stylesheet\" media=\"(prefers-color-scheme: dark)\" href=\"/css/modus-vivendi.css\" type=\"text/css\"/>")
(defvar blog-header "<div id=\"updated\">Updated: %C</div>
<div id=\"org-div-home-and-up\">
<a href=\"https://example.com/blog\">Blog</a>
<a href=\"https://example.com/\">Home</a>
</div>
")

(defvar blog-footer "<hr/>
<footer>
<div class=\"copyright-container\">
<div class=\"Copyright\">
Copyright &copy; 2017-2022 example some rights reserved<br/>
Content is available under
<a rel=\"license\" href=\"http://creativecommons.org/licenses/by-sa/4.0/\">
CC-BY-SA 4.0</a> unless otherwise noted
</div>
<div class=\"cc-badge\">
<a rel=\"license\" href=\"http://creativecommons.org/licenses/by-sa/4.0/\">
<img alt=\"Creative Commons License\"
     src=\"https://i.creativecommons.org/l/by-sa/4.0/88x31.png\" />
</a>
</div>
</div>
<div class=\"banner\">
</a>
</div>
<div class=\"generated\">
Created with %c on <a href=\"https://www.gnu.org\">GNU</a>/<a href=\"https://www.kernel.org/\">Linux</a>
</div>
</footer>")

(defun my/relative-path-expand (path)
  "Expand relative PATH from current buffer or file to a full path."
  (concat
   (if load-file-name
       (file-name-directory load-file-name)
     default-directory)
   path))

(defvar blog-base-directory
  (my/relative-path-expand "org/")
  "The `base-directory' for blog project.")

(defvar blog-publish-directory
  (my/relative-path-expand "html/")
  ;; "/ssh:root@example.com:/var/www/html/"
  "The `publishing-directory' for blog project.")

(setq org-publish-project-alist
      `(
	("index"
         :base-directory ,blog-base-directory
         :base-extension "org"
         :exclude ".*"
         :include ("index.org")
         :publishing-directory ,blog-publish-directory
         :publishing-function org-html-publish-to-html

         :html-head     ,blog-css
         :html-preamble "<div id=\"updated\">Updated: %C</div>"
         :html-postamble ,blog-footer)
	("blog"
	 :base-directory ,(concat blog-base-directory "blog/")
	 :base-extension "org"
	 :publishing-directory ,(concat blog-publish-directory "blog/")
	 :publishing-function org-html-publish-to-html

	 :auto-sitemap t
	 :sitemap-title "Blog Posts"
	 :sitemap-filename "index.org"
	 :sitemap-sort-files anti-chronologically
         :sitemap-format-entry org-sitemap-custom-entry-format

	 :html-head ,blog-css
	 :html-head-extra ,blog-css-extra
	 :html-preamble ,blog-header
	 :html-postamble ,blog-footer)
	("static"
	 :base-directory ,blog-base-directory
         :base-extension "css\\|js\\|png\\|jpg\\|gif\\|pdf\\|mp3\\|ogg\\|swf"
	 :recursive t
	 :publishing-directory ,blog-publish-directory
	 :publishing-function org-publish-attachment)
	("org" :components ("blog" "static"))))	      

makefile

all:
	emacs -Q --batch -l publish.el -f org-publish-all

publish: all
	rsync -e ssh -vr html/ root@example.com:/var/www/html/

clean:
	rm -r html/*

Comments:

Email questions, comments, and corrections to hi@smartisan.dev.

Submissions may appear publicly on this website, unless requested otherwise in your email.